外观模式

外观模式也叫门面模式注重统一的对象,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。

该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。

除了这个接口不允许有任何访问子系统的行为发生,是外界访问子系统内部的唯一通道,是一种比较常用的封装模式。

一般情况下,一个子系统只要一个门面,但若门面已经庞大到不能忍受的程度,可拆分成多个门面;需要子系统可以提供不同访问路径的情况,也可提供多个门面。

门面不参与子系统的业务逻辑,否则会产生倒依赖问题,子系统必须依赖门面才能被访问,违反了单一职责原则,同时也破坏了系统的封装性。

定义

要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行,外观模式提供一个高层次的接口,使得子系统更易于使用。

实现

外观模式类图

外观角色Facade:为多个子系统对外提供一个共同的接口。

1
2
3
4
5
6
7
8
9
10
11
public class Facade {
private SubSystem01 obj1 = new SubSystem01();
private SubSystem02 obj2 = new SubSystem02();
private SubSystem03 obj3 = new SubSystem03();

public void method() {
obj1.method1();
obj2.method2();
obj3.method3();
}
}

子系统角色SubSystem:实现系统的部分功能,客户可以通过外观角色访问它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class SubSystem01 {
public void method1() {
System.out.println("子系统01的method1()被调用");
}
}

public class SubSystem02 {
public void method2() {
System.out.println("子系统02的method2()被调用");
}
}

public class SubSystem03 {
public void method3() {
System.out.println("子系统03的method3()被调用");
}
}

客户角色Client:通过一个外观角色访问各个子系统的功能。

1
2
3
4
public static void main(String[] args) {
Facade facade = new Facade();
facade.method();
}

优点

  • 减少了系统的相互依赖,所有的依赖都是对门面对象的依赖,与子系统无关,降低了子系统与客户端之间的耦合度
  • 对客户屏蔽了子系统组件,减少了客户处理的对象数目,并使得子系统使用起来更加容易。
  • 提高了灵活性,不管子系统内部如何变化,只要不影响到门面对象,可随意修改
  • 提高了安全性,不在门面上开通的方法不能访问

缺点

  • 不符合开闭原则,增加新的子系统可能需要修改外观类或客户端的源代码

应用场景

  • 为一个复杂的模块或子系统提供一个供外界访问的接口
  • 子系统相对独立,外界对子系统的访问只要黑箱操作即可,如利息计算问题
  • 预防低水平人员带来的风险扩散
  • 对分层结构系统构建时,使用外观模式定义子系统中每层的入口点可以简化子系统之间的依赖关系
  • 当客户端与多个子系统之间存在很大的联系时,引入外观模式可将它们分离,从而提高子系统的独立性和可移植性。
  • 使用外观模式整合已有的API