2018-09-20 01:33:12linux
仍是用大话设计模式中的例子:股票和基金来讲明外观模式。股票买入者直接操做股票,他须要了解几千只股票的各类信息还须要预测它的涨跌,这样买入者和股票直接有着直接的联系,在软件开发种,这就是高耦合(模块和模块之间的联系过多)。买入基金,则由专业的基金经理人操做用户的资源,买入者只须要和基金经理人打交道,具体股票的细节,则由基金经理人来处理。ios
外观模式(Facade Pattern)又称门面模式:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。设计模式
其中:SubSystemOne、SubSystemTwo、SubSystemThree、SubSystemFour 构成了一个子系统。bash
Facade:外观类,知道哪些子系统,它们有哪些功能,通常Client把像子系统的请求委托给Facade,而后Facade再把这个请求转给适合的子系统对象。(System和Facade实际上是聚合关系,它们之间没有太多的耦合性)架构
SubSystem:子系统,子系统能够同时有多个,一个系统能够是类的集合或者是一个单独的类。每一个子系统能够单独被Client调用也能够被Facade调用,对于Client来讲它不知道有Facade的存在,Facade对子系统而言就是一个Client。ide
优势:函数
1.Client只与Facade打交道,下降了Client代码的复杂度。spa
2.下降了Client和System的耦合度,子系统有调整时不会影响到Client或者影响较小,可以经过调整Facade来适应子系统的改变。设计
3.下降了大型软件中的编译依赖性,并简化了系统在不一样平台之间而定移植过程,由于设计良好的子系统,通常而言是相互独立的,一个系统的改变不会影响到其它子系统,而子系统的内部变化(指实现细节)也不会影响到外观,因此只须要编译有变化的子系统便可(对GCC编译器)。code
4.模式仅提供了一个访问子系统的统一入口,可是并不阻止用户直接使用子系统类。
缺点:
1.不能很好地限制Client使用子系统,若是要给Client添加使用限制,将多是整个模式丧失它的灵活性,也会增长其复杂度(试想一下为每一个子系统添加定制化的限制,在实现是将会有多复杂)
2.在不引入抽象外观类(Facade)的状况下,增长子系统,要对应的调整Facade和Client(考虑下简单工厂模式),这会违背开放-封闭原则。
问题模型:假设咱们在开发一个GUI程序,经过界面咱们可以产生一组通用数据,可是这组通用数据须要被不一样的子系统按需选择,并进行对应的处理。好比咱们能在bash终端输入不一样的命令调用不一样的处理程序。咱们假设这是一个外观模式(但真实的应用状况不是这样,由于,linux下的各类命令其实是由我的开发者自行开发的程序,在使用时,bash终端输入程序名 参数便可使用命令提供的服务)。那么如今main函数就是客户代码,S1表示调用子系统S1执行某种操做,S2表示调用S2执行某种操做等等。网上有个电商的例子,我以为比较好,它没有我这个这么理想化,子系统之间的数据没有耦合。
1.3个子系统
#ifndef SUBSYSTEMA_H_ #define SUBSYSTEMA_H_ #include <iostream> class SubSystemA { public: void methodA() { std::cout << "I am SystemA!" << std::endl; } SubSystemA() = default; ~SubSystemA() = default; }; #endif
#ifndef SUBSYSTEMB_H_ #define SUBSYSTEMB_H_ #include <iostream> #include <ctime> class SubSystemB { public: void methodB() { auto systTime = time(nullptr); tm *struSysTime = localtime(&systTime); char szTime[16] = {0}; sprintf(szTime,"%04d-%02d-%02d",struSysTime->tm_year+1990,struSysTime->tm_mon+1,struSysTime->tm_mday); std::cout << "Today is:" << szTime << std::endl; } SubSystemB() = default; ~SubSystemB() = default; }; #endif
#ifndef SUBSYSTEMC_H_ #define SUBSYSTEMC_H_ #include <iostream> #include <ctime> class SubSystemC { public: void methodC() { auto systTime = time(nullptr); tm *struSysTime = localtime(&systTime); char szTime[16] = {0}; sprintf(szTime,"%02d:%02d:%02d",struSysTime->tm_hour,struSysTime->tm_min,struSysTime->tm_sec); std::cout << "Now Time is:"<< szTime << std::endl; } SubSystemC() = default; ~SubSystemC() = default; }; #endif
2.Facade外观类,也是这个模式的核心
#ifndef FACADE_H_ #define FACADE_H_ #include "SubSystemA.h" #include "SubSystemB.h" #include "SubSystemC.h" #include <string> class Facade { public: void noteSubSystem(const std::string strParam); Facade() = default; ~Facade() = default; private: SubSystemA m_objSubSystemA; SubSystemB m_objSubSystemB; SubSystemC m_objSubSystemC; }; #endif #include "Facade.h" void Facade::noteSubSystem(const std::string strSystemName) { if(strSystemName == "SubSystemA") m_objSubSystemA.methodA(); else if(strSystemName == "SubSystemB") m_objSubSystemB.methodB(); else if(strSystemName == "SubSystemC") m_objSubSystemC.methodC(); else std::cout << "Param Error" << std::endl; }
3.客户端代码
#include "Facade.h" using namespace std; int main(int argc,char*argv[]) { if(argc != 2) { std::cout << "The count of param is Error!" <<std::endl; return (0); } std::string strParam = argv[1]; Facade objFacade; objFacade.noteSubSystem(strParam); return (1); }
外观模式的使用:
1.在设计阶段就要有意识的把不一样的层分离(三层架构:数据访问层、业务逻辑层、表示层,在层与层之间创建外观Facade)
2.开发阶段,子系统由于不断的重构变的愈来愈复杂。增长外观模式。能够提供一个简单的接口,减小它们之间的依赖
3.为新系统开发一个外观Facade类,来提供设计粗糙或高度负责的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互全部的复杂工做。
d