Facade模式要求一个子系统的外部与其内部的通信必须通过一个统一的Facade对象进行。Facade模式提供一个高层次的接口,使得子系统更易于使用。
举一个生活中的小例子,大凡开过学或者毕过业的都会体会到这样一种郁闷:你要去 n个地方办理 n 个手续(现在大学合并后就更加麻烦,因为可能那 n 个地方都隔的比较远)。但是实际上我们需要的就是一个最后一道手续的证明而已,对于前面的手续是怎么办的、到什么地方去办理我们都不感兴趣。
实际上在软件系统开发中也经常回会遇到这样的情况,可能你实现了一些接口(模块),而这些接口(模块)都分布在几个类中(比如 A 和 B、C、D):A 中实现了一些接口,B 中实现一些接口(或者 A 代表一个独立模块,B、C、D 代表另一些独立模块)。然后你的客户程序员(使用你设计的开发人员)只有很少的要知道你的不同接口到底是在那个类中实现的,绝大多数只是想简单的组合你的 A-D 的类的接口,他并不想知道这些接口在哪里实现的。
这里的客户程序员就是上面生活中想办理手续的郁闷的人!在现实生活中我们可能可以很快想到找一个人代理所有的事情就可以解决你的问题(你只要维护和他的简单的一个接口而已了!),在软件系统设计开发中我们可以通过一个叫做 Façade 的模式来解决上面的问题。
其典型的结构图为:
大家都是高智商的人,都写过纸质的信件吧,比如给女朋友写情书什么的,写信的过程大家都还记得吧,先写信的内容,然后写信封,然后把信放到信封中,封好,投递到信箱中进行邮递,这个过程还是比较简单的,虽然简单,这四个步骤都是要跑的呀,信多了还是麻烦,比如到了情人节,为了大海捞针,给十个女孩子发情书,都要这样跑一遍,你不要累死,更别说你要发个广告信啥的,一下子发 1 千万封邮件,那不就完蛋了?那怎么办呢?还好,现在邮局开发了一个新业务,你只要把信件的必要信息高速我,我给你发,我来做这四个过程,你就不要管了,只要把信件交给我就成了。
我们的类图还是从最原始的状态开始:
在这中环境下,最累的是写信的人,为了发送一封信出去要有四个步骤,而且这四个步骤还不能颠倒,你不可能没写信就把信放到信封吧,写信的人要知道这四个步骤,而且还要知道这四个步骤的顺序,恐怖吧, 同时那这个过程与高内聚的要求相差甚远,你想,你要知道这四个步骤,而且还要知道这四个步骤的顺序,一旦出错,信就不可能邮寄出去,那我们如何来改进呢?先看类图(类名稍微变化,请注意):
注释:
main(),客户
ILetterProcess,接口
CLetterProcessImpl,信件处理的4个函数
CLetterPolice,警察
CModenPostOffice,邮局
说明:邮局对外只有一个窗口,接收信件内容和邮件地址。对内调用邮件处理的4个函数。将复杂逻辑封装在邮局的里面,当需要增加警察来检查信件时,只需在邮局内增加警察检查信件的方法。
注意:将复杂逻辑封装起来,对外只有一个简单的接口。
代码:
邮箱接口:ILetterProcess类
ILetterProcess.h
#ifndef __Facade__ILetterProcess__
#define __Facade__ILetterProcess__
#include
#include
using std::string;
class ILetterProcess {
public:
ILetterProcess(void){};
virtual ~ILetterProcess(void){};
virtual void WriteContext(string context) = 0;
virtual void FillEnvelope(string address) = 0;
virtual void LetterIntoEnvelope() = 0;
virtual void SendLetter() = 0;
};
#endif /* defined(__Facade__ILetterProcess__) */
LetterprocessImpl.h
#ifndef __Facade__LetterprocessImpl__
#define __Facade__LetterprocessImpl__
#include
#include "ILetterProcess.h"
class CLetterProcessImpl:public ILetterProcess
{
public:
CLetterProcessImpl(void);
~CLetterProcessImpl(void);
void WriteContext(string context);
void FillEnvelope(string address);
void LetterIntoEnvelope();
void SendLetter();
};
#endif /* defined(__Facade__LetterprocessImpl__) */
LetterprocessImpl.cpp
#include "LetterprocessImpl.h"
using std::string;
using std::cout;
using std::endl;
CLetterProcessImpl::CLetterProcessImpl(void)
{
}
CLetterProcessImpl::~CLetterProcessImpl(void)
{
}
void CLetterProcessImpl::WriteContext(string context)
{
cout << "填写信的内容... ..." << context << endl;
}
void CLetterProcessImpl::FillEnvelope(string address)
{
cout << "填写收件人地址及姓名... ..." << address << endl;
}
void CLetterProcessImpl::LetterIntoEnvelope()
{
cout << "把信放到信封中..." << endl;
}
void CLetterProcessImpl::SendLetter()
{
cout << "邮递信件..." << endl;
}
LetterPolice.h
#ifndef __Facade__LetterPolice__
#define __Facade__LetterPolice__
#include
#include "ILetterProcess.h"
class CLetterPolice
{
public:
CLetterPolice(void);
~CLetterPolice(void);
void CheckLetter(ILetterProcess *pLetterProcess);
};
#endif /* defined(__Facade__LetterPolice__) */
LetterPolice.cpp
#include "LetterPolice.h"
CLetterPolice::CLetterPolice(void)
{
}
CLetterPolice::~CLetterPolice(void)
{
}
void CLetterPolice::CheckLetter(ILetterProcess *pLetterProcess)
{
//检查信件,此处省略一万字。
std::cout<<"警察检查信件,此处省略一万字....." ;
return;
}
ModenPostOffice.h
#ifndef __Facade__ModenPostOffice__
#define __Facade__ModenPostOffice__
#include
#include "ILetterProcess.h"
#include "LetterprocessImpl.h"
#include "LetterPolice.h"
using std::string;
class CModenPostOffice
{
public:
CModenPostOffice(void);
~CModenPostOffice(void);
void SendLetter(string context,string address);
private:
ILetterProcess *m_pLetterProcess;
CLetterPolice *m_pLetterPolice;
};
#endif /* defined(__Facade__ModenPostOffice__) */
ModenPostOffice.cpp
#include "ModenPostOffice.h"
CModenPostOffice::CModenPostOffice(void)
{
this->m_pLetterProcess = new CLetterProcessImpl();
this->m_pLetterPolice = new CLetterPolice();
}
CModenPostOffice::~CModenPostOffice(void)
{
delete m_pLetterProcess;
delete m_pLetterPolice;
}
void CModenPostOffice::SendLetter(string context, string address)
{
//帮忙写信
m_pLetterProcess->WriteContext(context);
//写好信封
m_pLetterProcess->FillEnvelope(address);
//警察要检查信件了
m_pLetterPolice->CheckLetter(m_pLetterProcess);
//把信放到信封中
m_pLetterProcess->LetterIntoEnvelope();
//邮递信件
m_pLetterProcess->SendLetter();
}
main.cpp
#include
#include "ILetterProcess.h"
#include "LetterprocessImpl.h"
#include "ModenPostOffice.h"
using std::string;
using std::cout;
using std::endl;
void DoItByPostOffice()
{
CModenPostOffice modenPostOffice;
string context ="Hello, It's me, do you know who I am? I'm your old lover. I'd like to ... ...";
string address = "Happy Road No. 666, Beijing City, China";
modenPostOffice.SendLetter(context, address);
}
void DoItYourself()
{
ILetterProcess *pLetterProcess = new CLetterProcessImpl();
pLetterProcess->WriteContext("Hello, It's me, do you know who I am? I'm your old lover. I'd like to ... ...");
pLetterProcess->FillEnvelope("Happy Road No. 666, Beijing City, China");
pLetterProcess->LetterIntoEnvelope();
pLetterProcess->SendLetter();
delete pLetterProcess;
}
int main(int argc, const char * argv[])
{
//现在的调用方式。对于客户来说确实简单多了。
//如需要增加逻辑,例如让警察来检查邮件。可以在邮局里完成这项工作。
cout<<"**********Facade的调用方式**********\n";
DoItByPostOffice();
cout<<"**********原来的调用方式**********\n";
//原来的调用方式。
DoItYourself();
// insert code here...
std::cout << "Hello, World!\n";
return 0;
}
参考文献:《设计模式之禅》,《GoF_23种设计模式解析》
参考博客:http://www.cnblogs.com/wanggary/archive/2011/04/12/2014186.html