漫谈设计模式值外观模式(Facade)

什么是外观模式?外观模式也叫做门面模式,属于结构型设计模式中的一种。Gof给出的定义是:将子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。打个比方,就好比你在linux写的c/c++代码,你要编写makefile文件,然后执行make命令进行编译;但是,很多IDE比如Visual Studio,Qt Creator都会提供一个构建(Build)按钮去完成这一系列操作。这个统一的按钮就是高层接口,他把子系统也就是编写makefile文件,执行make命令这些子系统(或者说任务吧)都包在这个构建按钮中了,这样更方便客户端或者用户使用。


外观模式(Facade)模式UML结构图:

这个结构图我们可以清楚的看到Facade(外观界面)的OperationWrapper()方法把子系统一和子系统二的Operation()都包起来了,这样可以使不想了解这些子系统的具体实现而是只想使用这个系统的人提供一个方便的高层接口,亦或是一个高层API,亦或是我们前文提到的一个构建按钮。


示例代码:

#include <iostream>

using namespace std;

/**
 * @brief The SyntaxParser class
 * 语法分析子系统
 */
class SyntaxParser
{
public:
    void doSyntaxParser() {
        cout<<"Do syntax parser work\n";
    }
};

/**
 * @brief The GenerateMidCode class
 * 生成中间代码子系统
 */
class GenerateMidCode
{
public:
    void doGenerateMidCode() {
        cout<<"Do generate middle code work\n";
    }
};

/**
 * @brief The GenerateAssemblyCode class
 * 生成汇编代码子系统
 */
class GenerateAssemblyCode
{
public:
    void doGenerateAssemblyCode() {
        cout<<"Do generate assembly code work\n";
    }
};

/**
 * @brief The LinkSystem class
 * 链接生成可执行应用程序文件或者库文件子系统
 */
class LinkSystem
{
public:
    void doLinkSystem() {
        cout<<"Do link system work\n";
    }
};


/**
 * @brief The Facade class
 * 外观类将编译过程涉及的所有子系统
 * 所做的工作包装成一个高层的API
 * (doCompile())给客户端使用
 */
class Facade
{
public:
    void doCompile() {
        SyntaxParser syntaxParser;
        GenerateMidCode generateMidCode;
        GenerateAssemblyCode generateAssemblyCode;
        LinkSystem linkSystem;
        syntaxParser.doSyntaxParser();
        generateMidCode.doGenerateMidCode();
        generateAssemblyCode.doGenerateAssemblyCode();
        linkSystem.doLinkSystem();
    }
};


//客户端
int main()
{

    Facade facade;
    facade.doCompile();
    return 0;
}


运行结果:

示例代码如果没有使用外观模式的话,在客户端如果要进行编译动作时,就需实现doCompile()中实现的所有操作,好像是没有什么本质上的区别,不考虑客户端的话代码量好像也没多大的差别。但是,有的时候,客户端并不会非常熟悉子系统之间的关系,就好比,先进行语法分析,再生成中间代码,然后生成汇编代码,最后进行链接一样,不是每个人都知道要获得可执行程序文件或者库文件都要经历这几个过程,包括很多程序员(因为很多IDE都把这些过程通过一个构建按钮包装好了)。如果客户端不知道这个时序,或者那些不知道编译过程的程序员要编译自己的源代码,那怎么办?这个时候就可以使用外观模式了!外观模式让一切复杂的东西都变得简单了。


使用外观模式的优点:

1.外观模式对客户端屏蔽了子系统组件,因而减少了客户处理的对象的数目,并使得子系统使用起来更加方便;

2.外观模式实现了子系统与客户(端)之间的松耦合关系,而子系统内部的功能组件往往是紧耦合的;松耦合系统使得子系统的组件变化不会影响到它的客户。外观模式有助于建立层次结构系统,也有助于对对象之间的依赖关系分层。外观模式可以消除复杂的循环依赖关系。这一点在客户程序与子系统是分别实现的时候尤为重要。

使用场合:

1.当你要为一个复杂子系统提供一个简单接口时,子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具有可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。外观模式可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过Facade层;

2.当客户程序与抽象类的实现部分之间存在很大的依赖性。引入Facade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性;

3.当需要构建一个层次结构的子系统时,使用外观模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,我们就可以让它们仅通过Facade进行通讯,从而简化了它们之间的依赖关系。


总结:

外观模式简单易用,让客户端更简单的去使用子系统,《大话设计模式》中对外观模式的总结我觉得非常到位:

1.首先,在设计初期阶段,应该要有意识的将不同的两个层分离,比如经典的三层架构,就需要考虑在数据访问层和业务逻辑层和表示层的层与层之间建立外观Facade,这样可以为复杂的子系统提供一个简单的接口,使得耦合大大降低;

2.其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,大多数的模式使用时也都会产生很多很小的类,这本是好事,但也给外部调用它们的用户程序带来了使用上的困难,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖;

3.在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含非常重要的功能,新的需求开发必须依赖于它。此时用外观模式Facede也是非常合适的。你可以为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。


拓展:通常来讲,对于子系统的访问,我们提供一个Facade层,而这个Facade入口,只需要一个;也就是说在使用Facade时,我们可以使用单例模式(Singleton)来实现Facade模式。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值