举一个生活中的小例子,大凡开过学或者毕过业的都会体会到这样一种郁闷:你要去n个地方办理n个手续(现在大学合并后就更加麻烦,因为可能那n个地方都隔的比较远)。但是实际上我们需要的就是一个最后一道手续的证明而已,对于前面的手续是怎么办的、到什么地方去办理我们都不感兴趣。
实际上在软件系统开发中也经常回会遇到这样的情况,可能你实现了一些接口(模块),而这些接口(模块)都分布在几个类中(比如A和B、C、D):A中实现了一些接口,B中实现一些接口(或者A代表一个独立模块,B、C、D代表另一些独立模块)。然后你的客户程序员(使用你设计的开发人员)只有很少的要知道你的不同接口到底是在那个类中实现的,绝大多数只是想简单的组合你的A-D的类的接口,他并不想知道这些接口在哪里实现的。
这里的客户程序员就是上面生活中想办理手续的郁闷的人!在现实生活中我们可能可以很快想到找一个人代理所有的事情就可以解决你的问题(你只要维护和他的简单的一个接口而已了!),在软件系统设计开发中我们可以通过一个叫做Façade的模式来解决上面的问题。
2.2 模式选择
我们通过Facade模式解决上面的问题,其典型的结构图为:
图2-1:Facade Pattern结构图
Façade模式的想法、思路和实现都非常简单,但是其思想却是非常有意义的。并且Façade设计模式在实际的开发设计中也是应用最广、最多的模式之一。
一个简单的例子就是,我在开发Visual CMCS项目【注释1】时候,在Visual CMCS中我们将允许用户独立访问我们的编译子系统(词法、语法、语义、代码生成模块),这些都是通过特定的类实现的,我们通过使用Façade模式给用户提供一个高层的接口,供用户在不想了解编译器实现的情况下去使用或重用我们的设计和实现。我们将提供一个Compile类作为Façade对象。
【注释1】:Visual CMCS是笔者主要设计和完成的一个C_minus语言(C 语言的一个子集)的编译系统,该
系统可以生成源C-minus程序的汇编代码(并且可以获得编译中间阶段的各个输出,如:词法、语法、语义中间代码等。),并可执行。Visual CMCS将作为一个对教学、学习、研究开源的项目,它更加重要的特性是提供了一个框架(framework),感兴趣的开发人员可以实现、测试自己感兴趣的模块,而无需实现整个的编译系统。Visual CMCS采用VC++ 6.0的界面风格,更多内容请参见Visual CMCS网站。
2.3 实现
2.3.1 完整代码示例(code)
Facade模式的实现很简单,这里为了方便初学者的学习和参考,将给出完整的实现代码(所有代码采用C++实现,并在VC 6.0下测试运行)。 代码片断1:Façade.h //Facade.h #ifndef _FACADE_H_ #define _FACADE_H_ { public: Subsystem1(); ~Subsystem1(); void Operation(); }; { public: Subsystem2(); ~Subsystem2(); void Operation(); }; { public: Facade(); ~Facade(); void OperationWrapper(); Subsystem1* _subs1; Subsystem2* _subs2; }; 代码片断2:Façade.cpp //Facade.cpp #include "Facade.h" using namespace std; { } { } { cout<<"Subsystem2 operation.."<<endl; } { } { } { cout<<"Subsystem2 operation.."<<endl; } { this->_subs1 = new Subsystem1(); this->_subs2 = new Subsystem2(); } { delete _subs1; delete _subs2; } void Facade::OperationWrapper() { this->_subs1->Operation(); this->_subs2->Operation(); } 代码片断3:main.cpp //main.cpp #include "Facade.h" using namespace std; { Facade* f = new Facade(); f->OperationWrapper(); }
class Subsystem1
protected:
private:
class Subsystem2
protected:
private:
class Facade
protected:
private:
#endif //~_FACADE_H_
#include <iostream>
Subsystem1::Subsystem1()
Subsystem1::~Subsystem1()
void Subsystem1::Operation()
Subsystem2::Subsystem2()
Subsystem2::~Subsystem2()
void Subsystem2::Operation()
Facade::Facade()
Facade::~Facade()
#include <iostream>
int main(int argc,char* argv[])
return 0;
2.3.2 代码说明
Façade模式的实现很简单,多余的解释完全是没有必要。
2.4 讨论
Façade模式在高层提供了一个统一的接口,解耦了系统。设计模式中还有另一种模式Mediator也和Façade有类似的地方。但是Mediator主要目的是对象间的访问的解耦(通讯时候的协议),具体请参见Mediator文档。