由于上面外观模式的结构过于抽象,因此把它具体点。假设系统内有三个模块,分别是AModule,BModule和CModule,它们分别有一个示意的方法,那么整体结构如下图所示。
#include <iostream> #include <memory> /** * A模块接口 */ class AModuleApi { public: virtual void testA() = 0; virtual ~AModuleApi() {} }; /** * A模块接口具体实现 */ class AModuleImpl : public AModuleApi { public: void testA() override { std::cout << "operate method testA in AModule" << std::endl; } }; /** * B模块接口 */ class BModuleApi { public: virtual void testB() = 0; virtual ~BModuleApi() {} }; /** * C模块接口具体实现 */ class BModuleImpl : public BModuleApi { public: void testB() override { std::cout << "operate method testB in BModule" << std::endl; } }; /** * C模块接口 */ class CModuleApi { public: virtual void testC() = 0; virtual ~CModuleApi() {} }; /** * C模块接口具体实现 */ class CModuleImpl : public CModuleApi { public: void testC() override { std::cout << "operate method testC in CModule" << std::endl; } }; /** * 外观对象 */ class Facade { public: /** * 示意方法,满足客户需求的功能 */ static void test() { /** * 在内部实现的时候,可能会调用到内部的多个模块 * 用智能指针new模块对象,其实可以用局部对象调用, * 考虑到模块对象可能比较大,担心占用栈空间过大 */ std::shared_ptr<AModuleApi> aptr(new AModuleImpl()); aptr->testA(); std::shared_ptr<BModuleApi> bptr(new BModuleImpl()); bptr->testB(); std::shared_ptr<CModuleApi> cptr(new CModuleImpl()); cptr->testC(); } }; void test() { Facade::test(); } int main(int argc, char** argv) { test(); return 0; }
运行结果:
operate method testA in AModule operate method testB in BModule operate method testC in CModule
以上例子,Facade类其实相当于A,B,C模块的外观界面,Facade类也被称为A,B,C模块对外的接口,那么客户端就不需要知道系统内部的实现细节,甚至客户端都不需要知道A,B,C模块的存在,客户端跟Facade类交互就好了,从而更好实现了客户端和子系统中A,B,C模块的解耦,让客户端更容易地使用系统。
外观模式的目的不是给子系统添加新的功能接口,而是为了让外部减少与子系统内多个模块的交互,松散解耦,从而让外部能够更简单地使用子系统。这点要特别注意,因为外观是当做子系统对外接口的实现,虽然也可以在这里定义一些子系统没有到额功能,但不建议这么做。外观应该是包装已有的功能,它主要负责组合已有功能来实现客户需要,而不是添加新的实现。
能够选择性地暴露接口的方法,尽量减少子系统接口功能的暴露。一个模块的接口中定义的方法可以分为两部分,一部分是给子系统外部使用的,一部分是子系统内部的模块间相互调用时使用的。有了Facade接口,那么用于子系统内部的接口功能就不用暴露给子系统的外部。
封装交互,简化调用
原创声明,本文系作者授权云+社区发表,未经许可,不得转载。
如有侵权,请联系 yunjia_community@tencent.com 删除。
我来说两句