设计模式 11 外观模式
外观模式(Facade Pattern)属于结构型模式
概述
在生活中,经常遇到这样的情况:办理一个业务,需要找很多部门签字盖章,这些部门往往距离较远,无奈只得四处奔波。这时候相信所有人都有一个同样的诉求:要是找一个部门就能办理完所有业务就好了!
编程来源于生活,生活中是这样,代码中也是这样。如果一个业务逻辑需要调几个独立的系统,不仅编写复杂,还不方便管理和维护,任意系统的业务变更都将影响很多地方。这时也是同样的诉求,要是调一个系统就能解决业务就好了!
这时外观模式就应运而生了,它隐藏了各系统间调用的复杂性,并向客户端提供了可以一次访问就实现各系统间逻辑的接口。
外观模式充分体现了迪米特法则。一般大型项目都有很多个子系统,可以在这些子系统的上面加一个门面(Facade),当外部需要与各个子系统交互时,无需再去单独调用各个子系统,而是直接与门面进行交互,再由门面与后面的各个子系统操作。这样方便了调用方代码的编写,统一找门面就行,不需要去详细了解各个子系统,并且,当子系统需要修改时,只需修改门面中的逻辑,不需要变动调用方的代码,遵循迪米特法则尽可能少的交互,极大的提高了便利性和健壮性。
代码实现
这里以找各个部门办理业务为例介绍外观模式:
1、定义A部门
/**
* A部门
*/
public class DepartmentA {
/**
* 办理业务
*/
public void business() {
System.out.println("A部门办理了业务");
}
}
2、定义B部门
/**
* B部门
*/
public class DepartmentB {
/**
* 办理业务
*/
public void business() {
System.out.println("B部门办理了业务");
}
}
3、定义C部门
/**
* C部门
*/
public class DepartmentC {
/**
* 办理业务
*/
public void business() {
System.out.println("C部门办理了业务");
}
}
4、定义外观部门
/**
* 外观部门
*/
public class Facade {
/**
* A部门
*/
private DepartmentA departmentA;
/**
* B部门
*/
private DepartmentB departmentB;
/**
* C部门
*/
private DepartmentC departmentC;
/**
* 无参构造器中给包装的部门赋值
*/
public Facade() {
departmentA = new DepartmentA();
departmentB = new DepartmentB();
departmentC = new DepartmentC();
}
/**
* 办理业务
*/
public void business() {
departmentA.business();
departmentB.business();
departmentC.business();
}
}
5、调用
// 找到外观部门
Facade facade = new Facade();
// 办理业务
facade.business();
输出结果:
A部门办理了业务
B部门办理了业务
C部门办理了业务
如此即实现了找一个部门就办理了多个部门的业务。不管多复杂的业务,麻烦的都是外观部门,而不是办理业务的人。哪个部门的业务发生变化了,外观部门去跟它们沟通协调做相应调整就行,办理业务的人不用再熟悉调整后的业务,还像往常一样找外观部门办理即可。
这就是外观模式带来的巨大便利,希望现实生活中如此场景的外观模式也早日到来!
优缺点
优点
1、减少系统相互依赖。
2、提高灵活性。
3、提高了安全性。
缺点
不符合开闭原则,如果要改东西很复杂,继承重写都不合适。
使用场景
1、为复杂的模块或子系统提供外界访问的模块。
2、子系统相对独立。
3、预防低水平人员带来的风险。
注意事项
在层次化结构中,可以使用外观模式定义系统中每一层的入口。
参考
https://www.bilibili.com/video/BV1u3411P7Na?p=19&vd_source=299f4bc123b19e7d6f66fefd8f124a03