下面从以下几个方面来详细讲解外观模式:
外观模式的核心思想。
何时使用外观模式。
Java中的应用。
在真实的应用系统中,一个子系统可能由很多类组成。子系统的客户为了满足它们的需要,需要和子系统中的一些类进行交互。客户和子系统的类进行直接的交互会导致客户端对象和子系统之间高度耦合。如图12-18所示,X和Y对子系统内A、B和C都有调用,它们之间是高度耦合。
![]() |
外观模式为子系统提供了一个更高层次、更简单的接口,从而降低了子系统的复杂度和依赖,这使得子系统更易于使用和管理。外观是一个能为子系统和客户提供简单接口的类。当正确地应用外观时,客户不再直接与子系统中的类交互,而是与外观交互。外观承担与子系统中类交互的责任。实际上,外观是子系统与客户的接口,这样外观模式降低了子系统和客户的耦合度。如图12-19所示,在X、Y与A、B、C之间增加一个Fa?ade外观类,它们之间的调用只需要通过Fa?ade来进行。
![]() |
外观对象隔离了客户和子系统对象,从而降低了耦合度。当子系统中的类进行改变时,客户端不会像以前一样受到影响。尽管客户使用由外观提供的简单接口,但是当需要的时候,客户端还是可以视外观不存在,直接访问子系统中的底层次的接口。在这种情况下,它们之间的依赖/耦合度和原来一样。
外观模式也是由代理模式发展而来的,与代理模式类似,代理模式是一对一的代理,而外观模式是一对多的代理。与装饰模式不同的是,装饰模式为对象增加功能,而外观模式则是提供一个简化的调用方式。一个系统可以有多个外观类,每个门面类都只有一个实例,可以使用单例模式实现。
外观模式中包含3种角色:目标类、外观类、客户端类。以计算机的加载和关闭过程为例,这3类角色如下。
目标类:包括CPU、内存和硬盘。
外观类:即为计算机类。
客户端类:即为用户。
它们之间的依赖关系如图12-20所示。
![]() |
下面来看具体的实现。
(1)CPU类CPU.java的源代码如程序12-34所示,其中定义了启动和关闭CPU的函数。
程序12-34 CPU类CPU.java
package structure.facade; public class CPU { public void startup() { System.out.println("启动CPU"); } public void shutdown() { System.out.println("关闭CPU"); } }
(2)内存类Memory.java的源代码如程序12-35所示,其中定义了加载和清空内存的函数。
程序12-35 内存类Memory.java
package structure.facade; public class Memory { public void startup() { System.out.println("加载内存"); } public void shutdown() { System.out.println("清空内存"); } }
(3)硬盘类Disk.java的源代码如程序12-36所示,其中定义了加载和卸载硬盘的函数。
程序12-36 硬盘类Disk.java
package structure.facade; public class Disk { public void startup() { System.out.println("加载硬盘"); } public void shutdown() { System.out.println("卸载硬盘"); } }
(4)外观模式类Computer.java的源代码如程序12-37所示,其中包含了CPU、内存和硬盘3个类对象,并定义了启动和关闭计算机的函数,在启动和关闭时批量地启动和关闭CPU、内存和硬盘。
程序12-37 外观模式类Computer.java
package structure.facade; /** * @author liuzhongbing * 外观模式 */ public class Computer { private CPU cpu; private Memory memory; private Disk disk; public Computer() { cpu = new CPU(); memory = new Memory(); disk = new Disk(); } public void startup() { System.out.println("开始启动计算机"); cpu.startup(); memory.startup(); disk.startup(); System.out.println("启动计算机完成"); } public void shutdown() { System.out.println("开始关闭计算机"); cpu.shutdown(); memory.shutdown(); disk.shutdown(); System.out.println("关闭计算机完成"); } }
(5)内存类Memory.java的源代码如程序12-38所示,我们只需要调用Computer.java的函数来启动和关闭计算机,而不需要依次加载和关闭CPU、内存和硬盘。
程序12-38 用户类User.java
package structure.facade; public class User { public static void main(String args[]) { Computer computer = new Computer(); computer.startup(); computer.shutdown(); } }
运行该程序的输出如下:
开始启动计算机
启动CPU
加载内存
加载硬盘
启动计算机完成
开始关闭计算机
关闭CPU
清空内存
卸载硬盘
关闭计算机完成
从程序的输出可以看出,通过Computer一个外观类即可实现计算机所有部件的控制,而不需要单独去控制其所有的部件,这正是外观模式的作用。