一、模式动机
外观模式(Facade Pattern)是一种使用频率非常高的设计模式,它通过引入一个外观角色来简化客户端和子系统之间的操作,为复杂的子系统调用提供一个统一的入口,使子系统与客户端的耦合度降低,且客户端调用非常方便。
外观模式中,外部与一个子系统的通信可以通过一个统一的外观对象进行。外观模式又称为“门面模式”。也是对象结构型模式之一。
- 一个客户类需要和多个业务类交互,有时候这些需要交互的业务类会作为一个整体出现
- 引入一个新的外观类(Facade)来负责和多个业务类【子系统(Subsystem)】进行交互,而客户类只需与外观类交互
- 为多个业务类的调用提供了一个统一的入口,简化了类与类之间的交互
- 没有外观类:每个客户类需要和多个子系统之间进行复杂的交互,系统的耦合度将很大
- 引入外观类:客户类只需要直接与外观类交互,客户类与子系统之间原有的复杂引用关系由外观类来实现,从而降低了系统的耦合度功能
二、模式定义
- 外观模式(Facade Pattern):外部与子系统的通信通过一个统一的外观对象进行,为子系统中的一组接口提供一个统一的入口
- 外观模式定义了一个高层接口,这个接口使得子系统更加容易使用
- 外观模式又称为门面模式,它是一种对象结构型模式
三、模式结构
四、案例实现
案例背景
电源开关,可以控制电灯,风扇,空调和电视机的关闭
案例结构
代码实现
灯
public class Light {
private String position;
public Light(String position) {
this.position = position;
}
public void on(){
System.out.println(this.position+"开灯");
}
public void off(){
System.out.println(this.position+"关灯");
}
}
电视
public class Television {
public void on(){
System.out.println("开电视");
}
public void off(){
System.out.println("关电视");
}
}
空调
public class AirConditioner {
public void on(){
System.out.println("开空调");
}
public void off(){
System.out.println("关空调");
}
}
风扇
public class Fan {
public void on(){
System.out.println("开风扇");
}
public void off(){
System.out.println("关风扇");
}
}
开关
public class SwitchFacade {
private Light lights[] = new Light[4];
private Fan fan;
private AirConditioner airConditioner;
private Television television;
public SwitchFacade() {
lights[0] = new Light("左前");
lights[1] = new Light("左后");
lights[2] = new Light("右前");
lights[3] = new Light("右后");
fan = new Fan();
airConditioner = new AirConditioner();
television = new Television();
}
public void on(){
lights[0].on();
lights[1].on();
lights[2].on();
lights[3].on();
fan.on();
airConditioner.on();
television.on();
}
public void off(){
lights[0].off();
lights[1].off();
lights[2].off();
lights[3].off();
fan.off();
airConditioner.off();
television.off();
}
}
客户测试类
public class Client {
public static void main(String[] args) {
SwitchFacade switchFacade = new SwitchFacade();
switchFacade.on();
System.out.println("-------------------------------");
switchFacade.off();
}
}
运行结果
案例分析
开关类中关联子系统类,开关类中的方法是调用子系统的方法,如果要增加新的子系统,需要引进抽象外观类
五、模式分析
- 是迪米特法则的一种具体实现
- 通过引入一个新的外观角色来降低原有系统的复杂度,同时降低客户类与子系统的耦合度
- 所指的子系统是一个广义的概念,它可以是一个类、一个功能模块、系统的一个组成部分或者一个完整的系统
六、总结
模式优点
- 它对客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易
- 它实现了子系统与客户端之间的松耦合关系,这使得子系统的变化不会影响到调用它的客户端,只需要调整外观类即可
- 一个子系统的修改对其他子系统没有任何影响,而且子系统的内部变化也不会影响到外观对象
模式缺点
- 不能很好地限制客户端直接使用子系统类,如果对客户端访问子系统类做太多的限制则减少了可变性和灵活性
- 如果设计不当,增加新的子系统可能需要修改外观类的源代码,违背了开闭原则
使用情形
- 要为访问一系列复杂的子系统提供一个简单入口
- 客户端程序与多个子系统之间存在很大的依赖性
- 在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而是通过外观类建立联系,降低层之间的耦合度