C++设计模式之外观模式_C 语言

前言

在实际开发时,面对一个大的系统,总是会将一个大的系统分成若干个子系统,等子系统完成之后,再分别调用对应的子系统来完成对应的整体功能,这样有利于降低系统的复杂性;最终进行实现某个具体的功能时,我们将对应的子系统进行组合就好了;但是,子系统那么多,关系那么复杂,组合形成一个完整的系统,是存在难度的。

我们在使用visual studio进行编译C++代码时,你只是在菜单中选择了Build,然后visual studio就开始了一堆的编译工作;你应该知道,因为你的一个简单的Build动作,编译器在后台会进行语法分析,生成中间代码,生成汇编代码,链接成可执行程序或库等等动作;而这一切,作为只是开发程序的我们,而不用去理解编译器在做什么的,编译器向我们隐藏了背后的一系列复杂操作,而只提供一个Build按钮,这个Build按钮,就可以执行一切的操作;当单击这个Build按钮时,Build在幕后,将任务分发给不同的子系统去完成,最终子系统进行协作完成了整个的编译任务。而这样隐藏一些复杂操作,只提供一个更高层的统一接口,就是我今天总结的外观模式。

什么是外观模式?

外观模式,很多人也把它叫做门面模式。在GOF的《设计模式:可复用面向对象软件的基础》一书中对外观模式是这样说的:将子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。细细的理解这句话;子系统中的一组接口,就好比上面举得例子中的语法分析,生成中间代码,生成汇编代码,链接成可执行程序或库;外观模式定义的一个高层接口,就好比上面说的Build按钮,通过这样的一个Build按钮,让编译器更加容易使用,对于这一点,从Linux C++/C转Windows C++/C的程序员是最有体会的。visual studio提供的强大功能,只需要一个Build按钮,就可以进行Build动作,而不需要去写makefile文件,然后再去执行一些命令进行编译。

UML类图

Facade:知道哪些子系统类负责处理请求,并且将客户的请求代理给适当的子系统对象;

SubSystem:实现子系统具体的功能;处理由Facade对象指派的任务;但是,SubSystem没有Facade的任何相关信息,也就是说,没有指向Facade的指针。

Client通过发送请求给Facade的方式与子系统进行通信,而不直接与子系统打交道,Facade将这些消息转发给适当的子系统对象。尽管是子系统中的有关对象在做实际工作,但Facade模式本身也必须将它的接口转换成子系统的接口,这里是不是有点适配器模式的感觉呢?这就是学习结构型设计模式的感觉,感觉都很相似,但是仔细的去研究时,就会发现各自的用处。

代码实现

这里实现的代码就是参照我上面举的编译器的例子。

复制代码 代码如下:

/*
** FileName     : FacadePatternDemo
** Author       : Jelly Young
** Date         : 2014/1/2
** Description  : More information, please go to http://www.jb51.net
*/
 
#include <iostream>
using namespace std;
 
// 语法分析子系统
class CSyntaxParser
{
public:
     void SyntaxParser()
     {
          cout<<"Syntax Parser"<<endl;
     }
};
 
// 生成中间代码子系统
class CGenMidCode
{
public:
     void GenMidCode()
     {
          cout<<"Generate middle code"<<endl;
     }
};
 
// 生成汇编代码子系统
class CGenAssemblyCode
{
public:
     void GenAssemblyCode()
     {
          cout<<"Generate assembly code"<<endl;
     }
};
 
// 链接生成可执行应用程序或库子系统
class CLinkSystem
{
public:
     void LinkSystem()
     {
          cout<<"Link System"<<endl;
     }
};
 
class Facade
{
public:
     void Compile()
     {
          CSyntaxParser syntaxParser;
          CGenMidCode genMidCode;
          CGenAssemblyCode genAssemblyCode;
          CLinkSystem linkSystem;
          syntaxParser.SyntaxParser();
          genMidCode.GenMidCode();
          genAssemblyCode.GenAssemblyCode();
          linkSystem.LinkSystem();
     }
};
 
// 客户端
int main()
{
     Facade facade;
     facade.Compile();
}

上面的代码很简单。我们可以想象,如果没有使用外观模式,在客户端如果要进行Compile同样的动作时,就需要写一堆和Compile中一样的代码;是的,你会说,写就写吧。但是,有的时候,客户端并不会非常熟悉子系统之间的关系,就好比,先要进行语法分析,再生成中间代码,然后生成汇编语言,最后进行链接一样。如果客户端不知道这个时序,那怎么办?所以,外观模式让一切复杂的东西,使用起来都变的简单了。

优点

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

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

使用场合

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

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

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

总结

外观模式简单易用,让客户能更简单的去使用子系统;在拜读别人的文章时,有以下总结非常好,我也借鉴一下:

1.在设计初期,应该有意识的将不同层分离,比如常用的三层架构,就是考虑在数据访问层,与业务逻辑层表示层之间,建立Facade,使复杂的子系统提供一个简单的接口,降低耦合性;

2.在开发阶段,子系统往往因为不断的重构而变的越来越复杂,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖;

3.在维护阶段,可能这个系统已经非常难以维护和扩展了,此时你可以为新系统开发一个外观类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。

通常来讲,对于子系统的访问,我们提供一个Facade层,而这个Facade入口,只需要一个;也就是说在使用Facade时,我们可以使用单例模式来实现Facade模式。对于外观模式到此就总结完成了,肯定有一些地方遗漏了,请大家指正。我坚信,分享使我们更加进步。

时间: 2025-01-02 03:18:19

C++设计模式之外观模式_C 语言的相关文章

通过C++程序示例理解设计模式中的外观模式_C 语言

举一个生活中的小例子,大凡开过学或者毕过业的都会体会到这样一种郁闷:你要去 n个地方办理 n 个手续(现在大学合并后就更加麻烦,因为可能那 n 个地方都隔的比较远). 但是实际上我们需要的就是一个最后一道手续的证明而已,对于前面的手续是怎么办的.到什么地方去办理我们都不感兴趣. 实际上在软件系统开发中也经常回会遇到这样的情况,可能你实现了一些接口(模块),而这些接口(模块)都分布在几个类中(比如 A 和 B.C.D):A 中实现了一些接口,B 中实现一些接口(或者 A 代表一个独立模块,B.C.

C++设计模式之模板方法模式_C 语言

前言 离开了自己工作了将近两年的公司,日子不再有了忙碌,可以闲下来,躺在家里的床上,想着以后的路怎么走,说实话,真的很迷茫,从2012年毕业到现在,时间不长,但是学到的东西真的是非常有限,一直从事于Windows平台上的开发.说到Windows平台的开发,大家都肯定知道的HOOK的,即使不知道HOOK,对于COM应该也是知道的,我的系列博文中也对COM进行过全面的总结.说白了,HOOK就是在执行某个功能时,会有一个一系列的执行过程,对于这个过程一般都是固定的,比如:第一步执行什么,第二步干什么,

C++设计模式之解释器模式_C 语言

前言 那日,闲的无聊,上了一个在线编程学习网站:最近那个在线编程学习网站很火啊:之前,盖茨.扎克伯格等大人物都来宣传了,思想是人人都应该学习编程:我一想就这算怎么回事啊?这要是在中国,还让人活不?话题不扯开了,还是说我上了那个在线编程网站吧,首先是给你玩一个小游戏,激发你对编程的兴趣.游戏是这样的,网页上有一个编辑框,屏幕上有一只小狗,比如你在编辑框中输入这样的句子:down run 10:按下回车,这个时候,你就看到屏幕上的小狗向下跑动了10个方格大小的长度:你再输入up walk 5,按下回

C++设计模式之工厂模式_C 语言

由遇到的问题引出工厂模式 在面向对象系统设计中经常可以遇到以下的两类问题: ◆ 1.为了提高内聚(Cohesion)和松耦合(Coupling),我们经常会抽象出一些类的公共接口以形成抽象基类或者接口.这样我们可以通过声明一个指向基类的指针来指向实际的子类实现,达到了多态的目的.这里很容易出现的一个问题 n 多的子类继承自抽象基类,我们不得不在每次要用到子类的地方就编写诸如 new ×××;的代码.这里带来两个问题: 客户程序员必须知道实际子类的名称(当系统复杂后,命名将是一个很不好处理的问题,

C++设计模式之访问者模式_C 语言

前言 这是23+1(简单工厂模式)之中的最后一个了--访问者模式.访问者模式也是一个比较麻烦的设计模式.我也没有实战经验,对于访问者模式的理解完全来自GOF的<设计模式:可复用面向对象软件的基础>,而这篇文章就是根据对这本书的理解而写出来的.在读<设计模式:可复用面向对象软件的基础>的时候,让我想起自己做过的一个项目,该项目虽然没有使用访问者模式,但是,今天理解了该模式,如果使用该模式对之前做过的项目进行重构,将是一个不错的想法. 访问者模式 在GOF的<设计模式:可复用面向

C++设计模式之策略模式_C 语言

前言 刚刚加班回来:哎,公司规定平时加班只有10块钱的餐补:星期六和星期天加班,只给串休假:在国家规定的节假日按照3倍工资发放.那么对于这么多的计算加班费的方法,公司的OA系统是如何进行做的呢?这就要说到今天我这里总结的策略设计模式了. 策略模式 在GOF的<设计模式:可复用面向对象软件的基础>一书中对策略模式是这样说的:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.该模式使得算法可独立于使用它的客户而变化. 策略模式为了适应不同的需求,只把变化点封装了,这个变化点就是实现不同

C++设计模式之状态模式_C 语言

前言 在实际开发中,我们经常会遇到这种情况:一个对象有多种状态,在每一个状态下,都会有不同的行为.那么在代码中我们经常是这样实现的. 复制代码 代码如下: typedef enum tagState {      state,      state1,      state2 }State;   void Action(State actionState) {      if (actionState == state)      {           // DoSomething     

C++设计模式之备忘录模式_C 语言

前言 又到年底了,也静不下心来写代码了,大家都很浮躁:翻出经典的<仙剑奇侠传>玩一会:又要打大BOSS,先存一下档吧.这是我的习惯,在打大BOSS之前,都要先存一下档,要是打赢了,就再存一个档,覆盖之前的:如果打输了,就恢复之前的存档,接着重来.我想大家都是这么玩的吧.哎呀,总是打不过.好了,不玩了,但是,游戏中的那个存档行为却让我很着迷,它是如何实现的呢?带着好奇的心,去百度了一下:哦,原来如此.好吧,开始今天的总结吧--备忘录模式. 备忘录模式 在GOF的<设计模式:可复用面向对象软

C++设计模式之命令模式_C 语言

前言 又要过年了,又是一个抢票季:从大学起,到现在工作,一直都是在外地,离家千里:以前买票,曾经也去火车站通宵排队买票:直到12306的腾空出现,在电脑前不停止的点着鼠标刷票,那个时候12306很是脆弱,抢一张票更是难上加难:现在好了,慢慢强大的12306,买票时出现了一个排队系统,先买票,进入12306的排队系统:然后,系统一个一个的处理大家的请求,一旦你的购票请求进入了排队系统,你就无法再次进行刷票了,除非你退出排队系统:这就减少了购票者的刷票次数:减少了12306后台服务器的处理压力.那么