定义:
要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。此模式提供一个高层的接口,使得子系统更易于使用。
外观模式也被称为门面模式。无论做SDK还是封装API,大多会用到外观模式,通过一个外观类使得整个系统结构只有一个统一的高层接口,降低用户使用成本。
模式所涉及的角色有:
Client : 客户端程序。
Facade : 对外的统一入口,即外观对象。
SubSystem : 子系统或者子服务等等。
如电视机遥控板例子:
/**
* 频道系统
*/
public class ChannelSystem {
public void nextChannel() {
System.out.println("下一个频道");
}
public void prevChannel() {
System.out.println("上一频道");
}
}
/**
* 音量系统
*/
public class VoiceSystem {
public void turnUp() {
System.out.println("音量增大");
}
public void turnDown() {
System.out.println("音量减小");
}
}
/**
* 电源系统
*/
public class PowerSystem {
public void powerOn() {
System.out.println("开机");
}
public void powerOff() {
System.out.println("关机");
}
}
/**
* 外观类--遥控板
*/
public class TvController {
private PowerSystem mPowerSystem = new PowerSystem();
private VoiceSystem mVoiceSystem = new VoiceSystem();
private ChannelSystem mChannelSystem = new ChannelSystem();
public void powerOn() {
mPowerSystem.powerOn();
}
public void powerOff() {
mPowerSystem.powerOff();
}
public void turnUp() {
mVoiceSystem.turnUp();
}
public void turnDown() {
mVoiceSystem.turnDown();
}
public void nextChannel() {
mChannelSystem.nextChannel();
}
public void prevChannel() {
mChannelSystem.prevChannel();
}
}
优点:
对客户程序隐藏子系统细节,因而减少了客户对于子系统的耦合,能够拥抱变化;
外观类对子系统的接口封装,使得系统更易于使用;
更好的划分访问层次,通过合理使用Facade,可以帮助我们更好地划分访问的层次。有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到外观类中,这样既方便客户端使用,也很好地隐藏了内部的细节。
缺点:
外观类接口膨胀,由于子系统的接口都由外观类统一对外暴露,使得外观类的 API 接口较多,在一定程度上增加了用户使用成本;
外观类没有遵循开闭原则(对扩展开放,对修改关闭),当业务出现变更时,可能需要直接修改外观类。