版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34536551/article/details/89160536
目录
概述
外观模式是一种使用频率非常高的结构型设计模式,它通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的接口,降低子系统与客户端的耦合度,且客户端调用非常方便。
定义
外观模式(也称为门面模式):
- 为子系统中的一组接口提供一个一致的接口,此模式定义了一个更高级的接口,这个结口使得这子系统更加容易使用。
- 说白了就是:外观类提供了一个接口,只有通过该类的函数接口才可以访问这些子系统,就像有一个类将所有的类都包装起来,子系统类有的方法外观类都有。当客户端调用这个高级接口时,不用关心高层内部调用是如何组合底层方法的,也不用关心底层函数是如何实现的。
- Facade 外观角色: 在客户端可以调用它的方法,该角色持有所有底层类的对象,并且包含底层类中所有的方法,客户端通过调用该角色的方法来间接访问底层的子类。
- subsystem子系统角色:子系统相当于多个类的集合,门面角色将其封装起来,使得客户端并不能直接调用它们的方法。子系统可以有多个。
- Client:客户端,直接使用
Facade
接口提供的方法这里就可以看出来,对
Client
来说只需要知道Facade
一个就行,不需要知道Facade
内部的复杂逻辑和结构,降低用户的使用成本。
外观模式中所指的子系统是一个广义的概念,它可以是一个类、一个功能模块、系统的一个组成部分或者一个完整的系统。子系统类通常是一些业务类,实现了一些具体的、独立的业务功能,具体代码如下:
#include<iostream>
#include<string>
using namespace std;
class SubSystemOne final
{
public:
void MethodOne()
{
std::cout << "子系统方法一" << std::endl;
}
};
class SubSystemTwo final
{
public:
void MethodTwo()
{
std::cout << "子系统方法二" << std::endl;
}
};
class SubSystemThree final
{
public:
void MethodThree()
{
std::cout << "子系统方法三" << std::endl;
}
};
class SubSystemFour final
{
public:
void MethodFour()
{
std::cout << "子系统方法四" << std::endl;
}
};
class Facade final
{
private:
SubSystemOne one;
SubSystemTwo two;
SubSystemThree three;
SubSystemFour four;
public:
void MethodA()
{
std::cout << "方法组A()------" << std::endl;
one.MethodOne();
two.MethodTwo();
three.MethodThree();
cout << endl;
}
void MethodB()
{
std::cout << "方法组B()------" << std::endl;
two.MethodTwo();
three.MethodThree();
cout << endl;
}
};
int main()
{
{
Facade myFacade;
myFacade.MethodA();
myFacade.MethodB();
}
system("pause");
return 0;
}
可以看到,客户端通过访问外观类来调用子系统内部类的方法。客户端并不知道谁来执行该方法,只是知道子系统中有这个方法即可调用。
优点
- 能够减少各个类之间的相互依赖,现在只依赖于外观类.
- 外观模式为复杂子系统提供了一个简单接口,并不为子系统添加新的功能和行为。
- 外观模式并没有封装子系统的类,只是提供了简单的接口。 如果应用需要,它并不限制客户使用子系统类。
- 子系统中任何类对其方法的内容进行修改,不影响外观类的代码。
降低了客户类与子系统类的耦合度,实现了子系统与客户之间的松耦合关系
- 只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类
- 减少了与子系统的关联对象,实现了子系统与客户之间 的松耦合关系,松耦合使得子系统的组件变化不会影响到它的客户。
外观模式对客户屏蔽了子系统组件,从而简化了接口,减少了客户处理的对象数目并使子系统的使用更加简单。
- 引入外观角色之后,用户只需要与外观角色交互;
- 用户与子系统之间的复杂逻辑关系由外观角色来实现
降低原有系统的复杂度和系统中的编译依赖性,并简化了系统在不同平台之间的移植过程
- 因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不会影响到外观对象。
缺点
- 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”
- 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。
使用场景
- 构建一个有层次结构的子系统时,使用外观模式定义子系统中每层的入口点,如果子系统之间是相互依赖的,则可以让他们通过外观接口进行通信,减少子系统之间的依赖关系。这样可以对一个复杂的子系统对外提供一个简单的接口。
- 子系统往往会因为不断的重构演化而变得越来越复杂,大多数的模式使用时也会产生很多很小的类,这给外部调用他们的用户程序带来了使用的困难,我们可以使用外观类提供一个简单的接口,对外隐藏子系统的具体实现并隔离变化。
- 当维护一个遗留的大型系统时,可能这个系统已经非常难以维护和拓展,但因为它含有重要的功能,新的需求必须依赖于它,则可以使用外观类,来为设计粗糙或者复杂的遗留代码提供一个简单的接口,让新系统和外观类交互,而外观类负责与遗留的代码进行交互。
- 在层次化结构中,可以使用外观模式定义系统中每一层的入口 ,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。
客户程序与多个子系统之间存在很大的依赖性
- 引入外观类将子系统与客户以及其他子系统解耦,可以提高子系统的独立性和可移植性。
与适配器模式的区别
- 外观模式的实现核心主要是——由外观类去保存各个子系统的引用,实现由一个统一的外观类去包装多个子系统类,然而客户端只需要引用这个外观类,然后由外观类来调用各个子系统中的方法。
- 这样的实现方式非常类似适配器模式,然而外观模式与适配器模式不同的是:适配器模式是将一个对象包装起来以改变其接口,而外观是将一群对象 ”包装“起来以简化其接口。它们的意图是不一样的,适配器是将接口转换为不同接口,而外观模式是提供一个统一的接口来简化接口。