外观模式(Facade Pattern)
情景演绎
大家都会玩电脑,那么在玩电脑前开机总会经历如下步骤:启动CPU,启动内存,启动硬盘等,在关机的时候又要经历关闭CPU,关闭内存,关闭硬盘等繁琐的操作。这里你就需要一个外观模式了,通过实现一个更加合理的接口外观类将这些动作都包装起来,实现一键“开机”、一键“关机”。这就是外观模式的动机
模式定义
所谓外观模式就是提供一个统一的接口,用来访问子系统中的一群接口。外观模式定义了一个高层接口,让子系统更容易使用。
在引入外观模式后,客户只需要与外观角色打交道,客户与子系统的复杂关系有外观角色来实现,从而降低了系统的耦合度。
代码实现
//首先是三个组件
class CPU {
public void on() {System.out.println("CPU打开");}
public void off() {System.out.println("CPU关闭");}
}
class Memory {
public void on() {System.out.println("内存打开");}
public void off() {System.out.println("内存关闭");}
}
class Disk {
public void on() {System.out.println("硬盘打开");}
public void off() {System.out.println("硬盘关闭");}
}
// 然后是强大美观的外观类
public class Facade {
private CPU c;
private Memory m;
private Disk d;
Facade(CPU c, Memory m, Disk d) {
this.c=c;
this.m=c;
this.d=c;
}
public void on() {
c.on();
m.on();
d.on();
}
public void off() {
c.off();
m.off();
d.off();
}
}
//客户端
public class Client {
public static void main(String[] args) {
CPU c = new CPU();
Memory m = new Memory();
Disk d = new Disk();
Facade f = new Facade(c,m,d);
f.on();//一键开机
System.out.println("............电脑已开机,可以使用了...........");
f.off();//一键关机
System.out.println("............电脑已关机,可以休息了...........");
}
}
运行结果
从上面的使用通过使用外观模式,客户可以非常方便的实现比较复杂的功能。
模式优缺点
优点:
- 引入外观模式,是客户对子系统的使用变得简单了,减少了与子系统的关联对象,实现了子系统与客户之间的松耦合关系。
- 只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类
- 降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程
缺点:
- 不能很好地限制客户使用子系统类(例如可以在客户端类中直接调用Cpu c = new CPU();c.on() ),但是如果对客户访问子系统类做太多的限制则减少了可变性和灵活性
- 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”
使用场景
- 当要为一个复杂子系统提供一个简单接口时可以使用外观模式。
- 客户程序与多个子系统之间存在很大的依赖性。引入外观类将子系统与客户以及其他子系统解耦,可以提高子系统的独立性和可移植性
总结
- 外观模式的主要优点就在于减少了客户与子系统之间的关联对象,使用客户对子系统的使用变得简单了,也实现了客户与子系统之间的松耦合关系。它的缺点就在于违背了“开闭原则”。
- 如果需要实现一个外观模式,需要将子系统组合进外观中,然后将工作委托给子系统执行。