原理或定義
它隐藏系统的复杂性,并向客户端提供一个可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性,为子系统中的一组接口提供了一个统一的高层访问接口,这个接口使得子系统更容易被访问或使用。这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。
结构
门面角色( facade ):这是门面模式的核心。它被客户角色调用,因此它熟悉子系统的功能。它内部根据客户角色已有的需求预定了几种功能组合;
子系统角色(subsystem):实现了子系统的功能。对它而言, façade角色就和客户角色一样是未知的,它没有任何 façade角色的信息和链接;
客户角色:调用 façade角色来完成要得到的功能;
類圖
案例与代码
本模式以智能家电控制项目为示例
使用遥控器通过中央控制器控制DVD和音响
设备类:
public class DVDPlayer {
private static DVDPlayer instance = null;
private DVDPlayer() {
}
public static DVDPlayer getInstance() {
if (instance == null) {
instance = new DVDPlayer();
}
return instance;
}
public void on() {
System.out.println("DVDPlayer On");
}
public void off() {
System.out.println("DVDPlayer Off");
}
public void play() {
System.out.println("DVDPlayer is playing");
}
public void pause() {
System.out.println("DVDPlayer pause");
}
public void setdvd() {
System.out.println("DVDPlayer is setting dvd");
}
}
public class Stereo {
private static Stereo instance = null;
private int volume = 5;
private Stereo() {
}
public static Stereo getInstance() {
if (instance == null) {
instance = new Stereo();
}
return instance;
}
public void on() {
System.out.println("Stereo On");
}
public void off() {
System.out.println("Stereo Off");
}
public void setVolume(int vol) {
volume = vol;
System.out.println("the volume of Stereo is set to " + volume);
}
public void addVolume() {
if (volume < 11) {
volume++;
setVolume(volume);
}
}
public void subVolume() {
if (volume > 0) {
volume--;
setVolume(volume);
}
}
}
public class TheaterFacade {
private Stereo mStereo;
private DVDPlayer mDVDPlayer;
public TheaterFacade() {
mStereo = Stereo.getInstance();
mDVDPlayer = DVDPlayer.getInstance();
}
public void dvd_on(){
mDVDPlayer.on();
}
public void setdvd(){
mDVDPlayer.setdvd();
}
public void dvd_off(){
mDVDPlayer.off();
}
public void play() {
mDVDPlayer.play();
}
public void pause() {
mDVDPlayer.pause();
}
public void stereo_off(){
mStereo.on();
}
public void stereo_on(){
mStereo.off();
}
public void addVolume() {
mStereo.addVolume();
}
public void subVolume() {
mStereo.subVolume();
}
}
Client / 遥控器类:
public class Control {
private TheaterFacade facade;
public Control() {
facade = new TheaterFacade();
}
public void button1(){
facade.dvd_on();
}
public void button2(){
facade.setdvd();
}
public void button3(){
facade.dvd_off();
}
public void button4() {
facade.play();
}
public void button5() {
facade.pause();
}
public void button6(){
facade.stereo_off();
}
public void button7(){
facade.stereo_on();
}
public void button8() {
facade.addVolume();
}
public void button9() {
facade.subVolume();
}
}
提供一个统一的接口,来访问子系统中一群功能相关接口
最少知识原则:尽量减少对象之间的交互,只留几个“密友”
对象的方法调用范围:
该对象本身
作为参数传进来的对象
此方法创建和实例化的对象
对象的组件
使用場景
1. 为一个复杂子系统提供一个简单接口。
2.提高子系统的独立性。
3.在层次化结构中,可以使用Facade模式定义系统中每一层的入口
優缺點
主要优点有:
1.对客户程序隐藏子系统细节,因而减少了客户对于子系统的耦合,能够拥抱变化;
2.外观类对子系统的接口封装,使得系统更易于使用;
3.更好的划分访问层次。把需要暴露给外部的功能集中到外观类中,这样既方便客户端使用,也很好地隐藏了内部的细节。
缺点主要有:
1.外观类接口膨胀,由于子系统的接口都由外观类统一对外暴露,使得外观类的 API 接口较多,在一定程度上增加了用户使用成本;
2.外观类没有遵循开闭原则,当业务出现变更时,可能需要直接修改外观类。