1. 概述
外观模式是一种结构型设计模式, 能为程序库、 框架或其他复杂类提供一个简单的接口。
外观模式很简单也很实用,还是先从问题引入:假设你必须在代码中使用某个复杂的库或框架中的众多对象。 正常情况下, 你需要负责所有对象的初始化工作、 管理其依赖关系并按正确的顺序执行方法等。
最终, 程序中类的业务逻辑将与第三方类的实现细节紧密耦合, 使得理解和维护代码的工作很难进行。
比如举一个例子来说明,我们都知道,要办理一个什么证件是一件非常复杂的事情:比如小王要帮一个XX证,首先他要去A局盖章,然后去B局开证明,然后去C局核实最后才能成功。
但是这样太麻烦了,办个证要跑来跑去的,所以政府最近新出了惠民政策,开了一个D局,现在我们要帮XX证,只要直接去D局就OK了,D局的工作人员会帮我们跑上面的流程,所以以后我们只要直接和D局办理即可,无需了解背后繁杂的手续。如下图:
这里政府的惠民政策(开了D局),其实就是使用了外观模式。外观模式就是针对于关联了许多类且逻辑复杂的情况,客户端的逻辑会十分复杂,那要怎么解决呢?很简单,新建一个外观类,把原本的复杂逻辑都丢给这个外观类,即原本要在客户端中的很复杂的逻辑都在外观类中写成一个方法,以后使用的时候客户端直接调用外观类方法即可。即用一个类来表达了一个系统的功能。
外观模式还是很好理解的,就是在原本客户端与子系统之间插入了一个类,这个类拥有子系统的功能,也就说相当于提供了子系统的一个入口,以后我们都与这个入口交互即可。
- 总结
- 外观模式用于解决程序中类的业务逻辑将与第三方类的实现细节紧密耦合, 使得理解和维护代码的工作很难进行的情况。
- 外观模式使用了一个外观类,该类融合了一个系统的功能,以后客户端直接与外观类沟通即可,从而实现了代码简化。即用一个类来表达了一个系统的功能,以前是与系统沟通,现在是只与一个类沟通。
- 外观模式使用外观类,实现了代码的解耦,简化了代码
2. 特点
-
优点:你可以让自己的代码独立于复杂子系统
-
缺点:外观可能成为与程序中所有类都耦合的上帝对象
-
使用场景
-
如果你需要一个指向复杂子系统的直接接口, 且该接口的功能有限, 则可以使用外观模式。
子系统通常会随着时间的推进变得越来越复杂。 即便是应用了设计模式, 通常你也会创建更多的类。 尽管在多种情形中子系统可能是更灵活或易于复用的, 但其所需的配置和样板代码数量将会增长得更快。 为了解决这个问题, 外观将会提供指向子系统中最常用功能的快捷方式, 能够满足客户端的大部分需求。
-
如果需要将子系统组织为多层结构, 可以使用外观。创建外观来定义子系统中各层次的入口。 你可以要求子系统仅使用外观来进行交互, 以减少子系统之间的耦合。
-
3. 实现
-
UML类图
-
Java代码
- 子系统
/** * @Author: chy * @Description: 子系统一部分:A局 * @Date: Create in 10:47 2021/3/13 */ public class A { void seal(){ System.out.println("A局盖章"); } }
/** * @Author: chy * @Description: 子系统一部分:B局 * @Date: Create in 10:47 2021/3/13 */ public class B { void prove(){ System.out.println("B局开证明"); } }
/** * @Author: chy * @Description: 子系统一部分:C局 * @Date: Create in 10:47 2021/3/13 */ public class C { void check(){ System.out.println("C局核实"); } }
- 外观类
/** * @Author: chy * @Description: 外观类,D局 * @Date: Create in 10:47 2021/3/13 */ public class D { void doAll(){ A a = new A(); B b = new B(); C c = new C(); a.seal(); b.prove(); c.check(); } }
- 客户端
/** * @Author: chy * @Description: 客户端 * @Date: Create in 10:20 2021/3/13 */ public class Client { public static void main(String[] args) { // 以前的操作 A a = new A(); B b = new B(); C c = new C(); a.seal(); b.prove(); c.check(); System.out.println("==================="); // 现在的操作 D d = new D(); d.doAll(); } }
- 子系统