前言

尊重原创,本系列文本解析部分主要基于Candidate for Master’s Degree School of Computer Wuhan University的K_Eckel([email protected])《设计模式精解-GoF 23 种设计模式解析附 C++实现源码》。为了避免重造轮子,本系列博文对源码在ubuntu16.04下做了验证并上传到了gitee,再次感谢。

如有问题,可邮件联系我([email protected])并共同探讨解决方案。

目录

创建型模式(Creating Pattern)

Factory 模式 | AbstactFactory 模式 | Singleton 模式 | Builder 模式 | Prototype 模式

结构型模式(Structrual Pattern)

Bridge 模式 | Adapter 模式 | Decorator 模式 | Composite 模式 | Flyweight 模式 | Facade 模式 | Proxy 模式

行为型模式(Behavioral Pattern)

Template 模式 | Strategy 模式 | State 模式 | Observer 模式 | Memento 模式 | Mediator 模式 | Command 模式 | Visitor 模式 | Iterator 模式 | Interpreter 模式 | Chain of Responsibility 模式

Facade 模式简介:

  外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
  这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。
  比如去医院看病,可能要去挂号、门诊、划价、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。

问题

  举一个生活中的小例子,大凡开过学或者毕过业的都会体会到这样一种郁闷:你要去 n 个地方办理 n 个手续(现在大学合并后就更加麻烦,因为可能那 n 个地方都隔的比较远)。但是实际上我们需要的就是一个最后一道手续的证明而已,对于前面的手续是怎么办的、到什么地方去办理我们都不感兴趣。
  实际上在软件系统开发中也经常回会遇到这样的情况,可能你实现了一些接口(模块),而这些接口(模块)都分布在几个类中(比如 ABCD):A 中实现了一些接口,B 中实现一些接口(或者 A 代表一个独立模块,BCD 代表另一些独立模块)。然后你的客户程序员(使用你设计的开发人员)只有很少的要知道你的不同接口到底是在那个类中实现的,绝大多数只是想简单的组合你的 AD 的类的接口,他并不想知道这些接口在哪里实现的。这里的客户程序员就是上面生活中想办理手续的郁闷的人!在现实生活中我们可能可以很快想到找一个人代理所有的事情就可以解决你的问题(你只要维护和他的简单的一个接口而已了!),在软件系统设计开发中我们可以通过一个叫做 Façade 的模式来解决上面的问题。

模式选择

  我们通过 Facade 模式解决上面的问题,其典型的结构图为:

Facade Pattern
图 1:Facade 模式结构示意图 1

   Façade 模式的想法、思路和实现都非常简单,但是其思想却是非常有意义的。并且 Façade 设计模式在实际的开发设计中也是应用最广、最多的模式之一。

  一个简单的例子就是,在 Visual CMCS 项目里,在 Visual CMCS 中我们将允许用户独立访问我们的编译子系统(词法、语法、语义、代码生成模块),这些都是通过特定的类实现的,我们通过使用 Façade 模式给用户提供一个高层的接口,供用户在不想了解编译器实现的情况下去使用或重用我们的设计和实现。我们将提供一个 Compile 类作为 Façade 对象。

实现

完整代码示例( code)

  Flyweight 模式完整的实现代码(所有代码采用 C++实现,并在 Visual Studio Code,Version: 1.36.1 下测试运行)。
   源码gitee地址点击这里

代码目录结构:

1
2
3
4
5
6
7
8
9
10
11
PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\structuralPattern\Facade> tree /F
卷 Windows 的文件夹 PATH 列表
卷序列号为 F0C5-AFA6
C:.
├─include
│ Facade.h

└─src
a.out
Facade.cpp
main.cpp

Facade.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//Facade.h

#ifndef _FACADE_H_
#define _FACADE_H_

class Subsystem1
{
private:
/* data */
public:
Subsystem1(/* args */);
~Subsystem1();
void Operation();
};

class Subsystem2
{
private:
/* data */
public:
Subsystem2(/* args */);
~Subsystem2();
void Operation();
};

class Facade
{
private:
Subsystem1* _subs1;
Subsystem2* _subs2;

public:
Facade(/* args */);
~Facade();
void OperationWrapper();
};

#endif //~_FACADE_H_

Facade.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Facade.cpp

#include "../include/Facade.h"
#include <iostream>
using namespace std;

Subsystem1::Subsystem1(/* args */) {}
Subsystem1::~Subsystem1() {}
void Subsystem1::Operation() { printf("Subsystem1 operation.. \n"); }

Subsystem2::Subsystem2(/* args */) {}
Subsystem2::~Subsystem2() {}
void Subsystem2::Operation() { printf("Subsystem2 operation.. \n"); }

Facade::Facade(/* args */) {
this->_subs1 = new Subsystem1();
this->_subs2 = new Subsystem2();
}
Facade::~Facade() {
delete _subs1;
delete _subs2;
}
void Facade::OperationWrapper(){
this->_subs1->Operation();
this->_subs2->Operation();
}

main.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
// main.cpp

#include <iostream>
#include "../include/Facade.h"

using namespace std;

int main(int argc, char* argv[]) {
Facade* f = new Facade();
f->OperationWrapper();

return 0;
}

代码说明

   Facade 模式的实现很简单,多余的解释完全是没有必要。

编译运行结果:

1
2
3
4
5
PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\structuralPattern\Facade\src> g++ *.cpp -std=c++11
PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\structuralPattern\Facade\src> .\a.exe
Subsystem1 operation..
Subsystem2 operation..
PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\structuralPattern\Facade\src>

讨论

   Facade 模式在高层提供了一个统一的接口,解耦了系统。设计模式中还有另一种模式 Mediator 也和 Facade 有类似的地方。但是 Mediator 主要目的是对象间的访问的解耦(通讯时候的协议),具体请参见 Mediator 文档。