外观模式
外观模式应用场景
在现实生活中,常常存在要办一件事要经历很多的复杂程序,如大学新生入学的报道流程。可能如下
- 寻找自己所在的院系迎新人员
- 到达新生接待处进行新生资格审核,领取宿舍房间号、报到证
- 到达住宿管理中心办理住宿手续
- 财务处缴纳学费
- 保卫处户口迁移交户口迁移证
- 学工处办理保险
- 办理校园一卡通 后勤集团
- 办理党团关系
新生报道要同多个部门联系,这时要有一个综合部门能解决一切手续问题就好了
软件设计也是这样,当一个系统的功能越来越强,子系统会越来越多,客户对系统的访问也会变得越来越复杂,如果这时系统内部发生改变,客户端也要跟着改变,这违背了“开闭原则”,也违背了“迪米特法则”,必须有必要为子系统提供一个统一的接口,从而降低系统的耦合度,这就是外观模式的目标。
迪米特法则
迪米特法则(Law of Demeter )又叫做最少知识原则,也就是说,一个对象应当对其他对象尽可能少的了解。不和陌生人说话。英文简写为: LoD
。
迪米特法则的目的在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。
迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系——这在一定程度上增加了系统的复杂度。
实现要点
外观(Facade
)模式的结构比较简单,主要是定义了一个高层的接口,它包含了各个子系统的引用,客户端可以通过它访问各个子系统的功能
- 定义一个统一的高层接口
- 对所各子系统的访问,都通过统一接口进行
外观模式的实现方式
-
外观(
Facade
)模式包含一下主要角色。 -
外观角色:为多个子系统对外提供一个共同的接口
-
子系统角色(Sub System) : 实现系统的部分功能,客户可以通过外观角色访问它
-
客户(client)角色:可以通过外观角色访问各个子系统的功能
设计图
## 源码
#include <iostream>
class Sub1_Work1{
public:
void Working1(){
std::cout<<"Doing Sub1_Work1..."<<std::endl;
}
};
class Sub1_Work2{
public:
void Working2(){
std::cout<<"Doing Sub1_Work2..."<<std::endl;
}
};
class Sub2_Work3{
public:
void Working3(){
std::cout<<"Doing Sub2_Work3..."<<std::endl;
}
};
class Sub2_Work4{
public:
void Working4(){
std::cout<<"Doing Sub2_Work4..."<<std::endl;
}
};
class Work{
private:
Sub1_Work1 w1;
Sub1_Work2 w2;
Sub2_Work3 w3;
Sub2_Work4 w4;
public:
void Work1(){//总工作1
w1.Working1(),w2.Working2();
}
void Work2(){//总工作2
w2.Working2(),w3.Working3(),w4.Working4();
}
};
//client 程序
int main(){
Work w;
w.Work1();//调用总工作1
w.Work2();//调用总工作2
return 0;
}
外观模式的优点
- 简化调用
- 简化复杂的系统调用过程,无需对子系统进行深入了解,即可完成调用
- 降低耦合
- 使用外观模式,只与外观对象进行交互,不与复杂的子系统直接进行交互
- 降低了系统依赖性,使耦合关系更低,子系统内部的模块更容易扩展和维护
- 层次控制
- 层次结构复杂的系统,有些方法需要提供给系统外部调用,有些方法需要在内部使用
- 将提供的功能定义在外观类中,这样既方便调用,也能将系统内部细节隐藏起来
- 符合迪米特法则
- 降低了系统直接的耦合度
外观模式的缺点
- 子系统扩展风险
- 系统内部扩展子系统时,容易产生风险
- 不符合开闭原则
- 外观模式,扩展子系统时,不符合开闭原则
开闭原则
开放封闭原则(OCP,Open Closed Principle)是所有面向对象原则的核心。软件设计本身所追求的目标就是封装变化、降低耦合,而开放封闭原则正是对这一目标的最直接体现。其他的设计原则,很多时候是为实现这一目标服务的.
开闭原则的定义
Software entities like classes,modules and functions should be open for extension but closed for modifications 一个软件实体, 如类, 模块, 函数等应该对扩展开放, 对修改封闭.