设计模式之外观模式
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
解析这个定义:
- “统一的接口,用来访问子系统中的一群接口”,如果不这么做之前,当多个客户端时,每个客户端都需要实现调用一群接口的逻辑,实现重复且复杂。且客户端耦合每个子系统的具体实现,不符合开闭原则。用一个统一接口封装一群接口,客户端只需要依赖一个类的一个接口即可。
- “高层接口”,说明外观类是在子系统之上,这是一个架构结构上的变化。
没有外观模式时的实现:

// 子系统类(与之前相同)
class CPU {
public void start() { System.out.println("CPU启动"); }
}
class Memory {
public void load() { System.out.println("内存加载"); }
}
class HardDrive {
public void read() { System.out.println("硬盘读取"); }
}
// 客户端代码(直接调用子系统)
public class ClientWithoutFacade {
public static void main(String[] args) {
// 客户端需要知道所有子系统组件
CPU cpu = new CPU();
Memory memory = new Memory();
HardDrive hardDrive = new HardDrive();
// 客户端需要了解正确的启动顺序
cpu.start();
memory.load();
hardDrive.read();
System.out.println("计算机启动完成");
}
}
这个实现存在以下问题:
- 客户端复杂度高:客户端需要了解所有子系统组件及其交互方式。
- 紧耦合:客户端直接依赖具体子系统类,违反迪米特法则(最少知识原则)。
- 难以维护:如果启动顺序或组件变化,需要修改所有客户端代码。
当这些子系统的启动逻辑需要给许多个客户端使用时,很自然的会想到,将他们抽取到一个中间层去实现,客户端不需要知道这么多细节。

// 子系统类
class CPU {
public void start() { System.out.println("CPU启动"); }
}
class Memory {
public void load() { System.out.println("内存加载"); }
}
class HardDrive {
public void read() { System.out.println("硬盘读取"); }
}
// 外观类
class ComputerFacade {
private CPU cpu;
private Memory memory;
private HardDrive hardDrive;
public ComputerFacade() {
this.cpu = new CPU();
this.memory = new Memory();
this.hardDrive = new HardDrive();
}
public void start() {
cpu.start();
memory.load();
hardDrive.read();
System.out.println("计算机启动完成");
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ComputerFacade computer = new ComputerFacade();
computer.start(); // 只需调用一个简单方法
}
}
咋一看,似乎并没有什么区别,在client中简化的操作,被移到了facade类中去了而已。关键在于这种移动带来的架构层面的优势,而不仅仅是代码位置的改变。
没有Facade时,责任分散在所有客户端中,每个使用子系统的客户端都必须了解,当启动顺序需要变成memory.load() → hardDrive.read() → cpu.start()
时,必须修改所有客户端。
而使用Facade后,责任集中在Facade这一个类中,所有客户端只需要知computer.start();
,隐藏具体细节,修改启动顺序时,只需修改ComputerFacade
类。
外观模式比较简单,它的价值在于:集中控制点、知识封装、批量维护优势。