企业官方网站需要备案吗,网站建设行业标准,网站上文章加入音乐是怎么做的,沈阳建设工程信息网 采购甲方都在中项网系列文章目录
C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列
期待你的关注哦#xff01;#xff01;#xff01;
现在的一切都是为将来的梦想编织翅膀#xff0c;让梦想在现实中展翅高飞。 Now everythi…系列文章目录
C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列
期待你的关注哦
现在的一切都是为将来的梦想编织翅膀让梦想在现实中展翅高飞。 Now everything is for the future of dream weaving wings, let the dream fly in reality. 结构型设计模式之外观模式 系列文章目录一、外观模式介绍二、外观模式优缺点2.1 优点2.2 缺点 三、外观模式使用场景四、外观模式实现五、外观模式应用实例 一、外观模式介绍
⚠️ 意图 为子系统中的一组接口提供一个一致的界面外观模式定义了一个高层接口这个接口使得这一子系统更加容易使用。
⚠️ 主要解决 降低访问复杂系统的内部子系统时的复杂度简化客户端之间的接口。
⚠️ 何时使用 1、客户端不需要知道系统内部的复杂联系整个系统只需提供一个接待员即可。 2、定义系统的入口
⚠️ 如何解决 客户端不与系统耦合外观类与系统耦合。 图1_1 外观模式类图 1外观模式符合是“迪米特法则”通过引入一个新的外观类可以降低原有系统的复杂度外观类充当了客户类与子系统类之间的“第三者”同时降低客户类与子系统类的耦合度。外观模式就是实现代码重构以便达到“迪米特法则”要求的一个强有力的武器。
2外观模式要求一个子系统的外部与其内部的通信通过一个统一的外观对象进行外观类将客户端与子系统的内部复杂性分隔开使得客户端只需要与外观对象打交道而不需要与子系统内部的很多对象打交道。
3外观模式从很大程度上提高了客户端使用的便捷性使得客户端无须关心子系统的工作细节通过外观角色即可调用相关功能。
4不要试图通过外观类为子系统增加新行为 不要通过继承一个外观类在子系统中加入新的行为这种做法是错误的。外观模式的用意是为子系统提供一个集中化和简化的沟通渠道而不是向子系统加入新的行为新的行为的增加应该通过修改原有子系统类或增加新的子系统类来实现不能通过外观类来实现。
5在外观模式中通常只需要一个外观类并且此外观类只有一个实例。在很多情况下为了节约系统资源一般将外观类设计为单例类。当然并不意味着在整个系统里只能有一个外观类在一个系统中可以设计多个外观类每个外观类都负责和一些特定的子系统交互向用户提供相应的业务功能。
6当增加新的子系统或者移除子系统时需要修改外观类可以通过引入抽象外观类在一定程度上解决该问题客户端针对抽象外观类进行编程。对于新的业务需求不修改原有外观类而对应增加一个新的具体外观类由新的具体外观类来关联新的子系统对象同时通过修改配置文件来达到不修改源代码并更换外观类的目的。
二、外观模式优缺点
2.1 优点 对客户屏蔽子系统组件减少了客户处理的对象数目并使得子系统使用起来更加容易。通过引入外观模式客户代码将变得很简单与之关联的对象也很少。 实现了子系统与客户之间的松耦合关系使得子系统的组件变化不会影响到调用它的客户类只需要调整外观类即可。 降低了大型软件系统中的编译依赖性并简化了系统在不同平台之间的移植过程因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响而且子系统内部变化也不会影响到外观对象。 只是提供了一个访问子系统的统一入口并不影响用户直接使用子系统类。
2.2 缺点 不能很好地限制客户使用子系统类如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。 在不引入抽象外观类的情况下增加新的子系统可能需要修改外观类或客户端的源代码违背了“开闭原则”。
三、外观模式使用场景 当要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类使得子系统更具可重用性也更容易对子系统进行定制但也给那些不需要定制子系统的用户带来一些使用上的困难。facade可以提供一个简单的缺省视图视图对大多数用户来说已经足够而那些需要更多的可定制性的用户可以越过facade层。 客户程序与抽象类的实现部分之间存在着很大的依赖性。引入 facade将这个子系统与客户以及其他的子系统分离可以提高子系统的独立性 和可移植性。 当你需要构建一个层次结构的子系统时使用 facade模式定义子系统中每层的入口点。如果子系统之间是相互依赖的你可以让它们仅通过facade进行通讯从而简化了它们之间的依赖关系。
适配器模式和外观模式共同点是将不好用的几口适配成好用的接口。但是适配器模式是将一个接口通过适配来间接转换为另一个接口外观模式主要是提供一个整洁的一致的接口给客户端。
抽象工厂模式可以与外观模式一起使用以提供一个接口用来以一种子系统独立的方式创建子系统对象。
中介者模式与外观模式抽象了一些已有的类的功能。中介者模式的目的是对同事之间的任意通讯进行抽象通常集中不属于任何单个对象的功能。中介者模式的同事对象知道中介者并与中介者通信而不是直接与其他同类对象通信。外观模式仅对子系统对象的接口进行抽象从而使子系统的接口更容易使用外观模式并不定义新功能子系统也不知道Facade的存在。
一般仅需要一个Facade对象因此Facade对象通常属于Singleton模式。
四、外观模式实现
Facade外观类
#ifndef FACADE_H
#define FACADE_H
#include iostream
#include SubSystemA.h
#include SubSystemB.hclass Facade
{
public:Facade(){m_pSubSystemA new SubSystemA();m_pSubSystemB new SubSystemB();}~Facade(){delete m_pSubSystemA;delete m_pSubSystemB;m_pSubSystemA NULL;m_pSubSystemB NULL;}void operationWrapper(){m_pSubSystemA-operation();m_pSubSystemB-operation();}
private:SubSystemA* m_pSubSystemA;SubSystemB* m_pSubSystemB;
};#endif // FACADE_HSubSystemA子系统类
#ifndef SUBSYSTEMA_H
#define SUBSYSTEMA_H
#include iostreamclass SubSystemA
{
public:SubSystemA(){}~SubSystemA(){}void operation(){std::cout SubSystemA::operation std::endl;}
};#endif // SUBSYSTEMA_HSubSystemB子系统类
#ifndef SUBSYSTEMB_H
#define SUBSYSTEMB_H
#include iostreamclass SubSystemB
{
public:SubSystemB(){}~SubSystemB(){}void operation(){std::cout SubSystemB::operation std::endl;}
};#endif // SUBSYSTEMB_H客户调用程序
#include Facade.hint main()
{Facade* facade new Facade();facade-operationWrapper();return 0;
}五、外观模式应用实例
假设编译一个程序需要经过四个步骤词法分析、语法分析、中间代码生成、机器码生成。对于编译器系统可以使用外观模式定义一个高层接口Compiler类Compiler有一个名为compile的函数。客户只需调用compile函数就可以编译程序compile函数内部的具体操作客户无需知道。
#include iostreamusing namespace std;//subsystem
class Scanner
{
public:void scan(){cout scanning... endl;}
};class Parser
{
public:void parse(){cout parsing... endl;}
};class GenMidCoder
{
public:void generateCode(){cout generating middle code.... endl;}
};class GenMachineCoder
{
public:void generateCode(){cout generating machine code.... endl;}
};//Facade
class Compiler
{
public:void compile(){Scanner sanner;Parser parser;GenMidCoder genMidCoder;GenMachineCoder genMachineCoder;sanner.scan();parser.parse();genMidCoder.generateCode();genMachineCoder.generateCode();}
};int main()
{Compiler compiler;compiler.compile();return 0;
}