原理或定義
它隱藏系統的複雜性,並向客戶端提供一個可以訪問系統的接口。這種類型的設計模式屬於結構型模式,它向現有的系統添加一個接口,來隱藏系統的複雜性,爲子系統中的一組接口提供了一個統一的高層訪問接口,這個接口使得子系統更容易被訪問或使用。這種模式涉及到一個單一的類,該類提供了客戶端請求的簡化方法和對現有系統類方法的委託調用。
結構
門面角色( 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.外觀類沒有遵循開閉原則,當業務出現變更時,可能需要直接修改外觀類。