外观模式--外部与一个子系统的通信必须通过一个统一的门面(Facade)对象进行,这就是门面模式。
医院的例子
用一个例子进行说明,如果把医院作为一个子系统,按照部门职能,这个系统可以划分为挂号、门诊、划价、化验、收费、取药等。看病的病人要与这些部门打交道,就如同一个子系统的客户端与一个子系统的各个类打交道一样,不是一件容易的事情。
首先病人必须先挂号,然后门诊。如果医生要求化验,病人必须首先划价,然后缴款,才能到化验部门做化验。化验后,再回到门诊室。
解决这种不便的方法便是引进门面模式。可以设置一个接待员的位置,由接待员负责代为挂号、划价、缴费、取药等。这个接待员就是门面模式的体现,病人只接触接待员,由接待员负责与医院的各个部门打交道。
什么是门面模式
门面模式要求一个子系统的外部与其内部的通信必须通过一个统一的门面(Facade)对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。
就如同医院的接待员一样,门面模式的门面类将客户端与子系统的内部复杂性分隔开,使得客户端只需要与门面对象打交道,而不需要与子系统内部的很多对象打交道。
以上取自别人的博文,原文http://www.cnblogs.com/zhenyulu/articles/55992.html,写得非常好这里就引用了。
下面是未使用外观模式的代码。
// facade.cpp : 定义控制台应用程序的入口点。
//
#include<iostream>
#include<string>
using namespace std;
class Patient
{
public:
Patient(string name)
{
this->name = name;
}
string name;
};
class Register
{
public:
void toDo(Patient &p)
{
cout <<p.name<<"去挂号" << endl;
}
};
class OutPatientDdepartment
{
public:
void toDo(Patient &p)
{
cout <<p.name<< "去门诊" << endl;
}
};
class Fee
{
public:
void toDo(Patient &p)
{
cout <<p.name<< "去付费" << endl;
}
};
class Medicine
{
public:
void toDo(Patient &p)
{
cout <<p.name << "去取药" << endl;
}
};
int main()
{
Patient p("patient");
Register r;
OutPatientDdepartment o;
Fee f;
Medicine m;
r.toDo(p);
o.toDo(p);
f.toDo(p);
m.toDo(p);
return 0;
}
这里为了简单把几个类写到一起了,理论上应该每个类有自己的头文件和源文件的。编译时也是各自编译成目标文件再链接成可执行程序的。
个人理解:程序主要分为两部分,客户程序代码和接口程序代码,原则就是客户程序代码
使用接口程序代码,接口设计得好,那么当一方有变动时,不会影响另一方,客户程序代
码对接口程序代码知道的越少,调用起来越简单越好。所以把接口程序的调用封装起来直
接提供给客户程序使用。外观模式体现较为明显。
这里main和patient对应的就是客户程序代码,其他的各个类则是接口程序代码。
patient要对各个类都清楚才可以。如果去挂号的方法名发生变化,或者参数变化,或者不须要挂号这个流程了,则客户程序和接口程序都要重新修改和编译。
而如果有一个接待员的话来负责病人的所有看病流程的话,病人只要知道接待员就可以了。
// facade.cpp : 定义控制台应用程序的入口点。
//
#include<iostream>
#include<string>
using namespace std;
class Patient
{
public:
Patient(){}
Patient(string name)
{
this->name = name;
}
string name;
};
class Register
{
public:
void toDo(Patient &p)
{
cout <<p.name<<"去挂号" << endl;
}
};
class OutPatientDdepartment
{
public:
void toDo(Patient &p)
{
cout <<p.name<< "去门诊" << endl;
}
};
class Fee
{
public:
void toDo(Patient &p)
{
cout <<p.name<< "去付费" << endl;
}
};
class Medicine
{
public:
void toDo(Patient &p)
{
cout <<p.name << "去取药" << endl;
}
};
class DeskClerk
{
public:
void setPatient(Patient &p)
{
this->p = p;
}
void toDo()
{
Register r;
OutPatientDdepartment o;
Fee f;
Medicine m;
r.toDo(p);
o.toDo(p);
f.toDo(p);
m.toDo(p);
}
Patient p;
};
int main()
{
Patient p("patient");
DeskClerk d;
d.setPatient(p);
d.toDo();
return 0;
}
客户代码简单多了,即始看病流程发生变化,也不会影响客户代码。