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