一、概述 外觀模式提供了一個統一的介面,用來訪問子系統中的一群介面。外觀定義了一個高層介面,讓子系統更容易使用。 二、解決問題 在上一講中,我們學習了適配器模式,它是用來轉換一個介面的,而外觀模式可以理解為轉換一群介面,客戶只要調用一個介面,而不用調用多個介面就可以達到目的。想想現實生活中例子,我們 ...
一、概述
外觀模式提供了一個統一的介面,用來訪問子系統中的一群介面。外觀定義了一個高層介面,讓子系統更容易使用。
二、解決問題
在上一講中,我們學習了適配器模式,它是用來轉換一個介面的,而外觀模式可以理解為轉換一群介面,客戶只要調用一個介面,而不用調用多個介面就可以達到目的。想想現實生活中例子,我們在pc上安裝軟體的時候經常有預設安裝或者是一鍵安裝選項(省去選擇安裝目錄、安裝的組件等等),還有就是手機的重啟功能(把關機和啟動合為一個操作)。總之,外觀模式就是解決多個複雜介面帶來的使用困難,起到簡化用戶操作的作用。
三、結構類圖
四、成員角色
客戶(Client):直接調用外觀介面就可以使用子系統了。
外觀(Facade):封裝子系統的一個或者多個介面,並提供一個統一的介面給客戶端調用。
五、應用實例
最近幾年一直比較流行智能家居,在我看來就是很多家電連了網,我們可以在手機上操作這些家電,給我們帶來了很大的便利。下麵我們假設這樣一種場景,我們晚上回到家需要開燈、開空調、關窗、拉窗帘、放音樂,完成這五個動作我們才可以舒舒服服地躺在沙發上,緩解一天工作的辛勞。如果每天要進行這樣的操作就太麻煩了,現在我們的智能家居來了,他給我們提供了一個手機app,只要將近到家的時候按下一個按鈕,各種家電就會自動工作,營造一個舒適的家庭環境等著我們回來。來看看我們是怎麼做到的。
第一步、創建各種電器
package facade.pattern; //電燈 public class Light { public void on(){ System.out.println("電燈打開了"); } public void off(){ System.out.println("電燈關了"); } }
package facade.pattern; //空調 public class Aircondition { public void on(){ System.out.println("空調打開了"); } public void off(){ System.out.println("空調關了"); } }
package facade.pattern; //窗 public class Window { public void on(){ System.out.println("窗打開了"); } public void off(){ System.out.println("窗關了"); } }
package facade.pattern; //窗帘 public class Curtain { public void on(){ System.out.println("窗帘打開了"); } public void off(){ System.out.println("窗帘關了"); } }
package facade.pattern; //mp3播放器 public class Mp3player { public void on(){ System.out.println("mp3播放器打開了"); } public void off(){ System.out.println("mp3播放器關了"); } }
第二步、創建手機app
package facade.pattern; //手機app public class App { private Light light; private Aircondition aircondition; private Window window; private Curtain curtain; private Mp3player mp3; //實例化時初始化電器 public App(Light light, Aircondition aircondition, Window window, Curtain curtain, Mp3player mp3) { super(); this.light = light; this.aircondition = aircondition; this.window = window; this.curtain = curtain; this.mp3 = mp3; } //設置在家模式,開啟需要的家電 public void atHome(){ light.on(); aircondition.on(); window.off(); curtain.off(); mp3.on(); } }
第三步、測試手機app
package facade.pattern; public class AppTest { public static void main(String[] args){ Light light = new Light(); Aircondition aircondition = new Aircondition(); Window window = new Window(); Curtain curtain = new Curtain(); Mp3player mp3 = new Mp3player(); App app = new App(light,aircondition,window,curtain,mp3); //以上代碼客戶可以不用知道 System.out.println("---用手機設置智能家居,設置為在家模式---"); //客戶一鍵操作設置在家模式 app.atHome(); } }
運行結果:
六、優點和缺點
1、優點
(1)、外觀不只是簡化了介面,也將客戶從組建的子系統中解耦。客戶只需關註外觀提供的介面,而不需要關心外觀所封裝的子系統的類。
(2)、提供簡化的介面的同時,依然將系統完整的功能暴露出來,以供需要的人使用。
七、使用場景
1、當需要簡化並統一一個很大的介面或者簡化一群複雜的介面時使用外觀。
2、希望客戶從一個複雜的子系統中解耦。
八、在外觀模式中可以使用的設計原則--最少知識原則
最少知識原則定義:只和你的密友交談。
最少知識原則設計方針是在就任何對象而言,在該對象的方法內,我們只應該調用屬於以下範圍的方法:
1、該對象本身
package facade.pattern; public class LightTest { public void on(){ System.out.println("電燈打開了"); } public void off(){ System.out.println("電燈關了"); } public void test(){ //在方法中調用本類中的其他方法 on(); } }
2、被當做方法的參數而傳遞進來的對象(外觀模式手機app的例子)
//手機app public class App { //外出模式 public void goOut(Light light, Aircondition aircondition, Window window, Curtain curtain, Mp3player mp3){ light.off(); aircondition.off(); window.on(); curtain.on(); mp3.off(); } }
3、此方法所創建或實例化的任何對象
//手機app public class App { private Light light; private Aircondition aircondition; private Window window; private Curtain curtain; private Mp3player mp3; public App(){ } public Mp3player getMp3() { return mp3; } public void setMp3(Mp3player mp3) { this.mp3 = mp3; } public void startMp3(){ mp3.on(); } }
//不建議如下使用
public void startMp3player(){ Mp3player mp3 = new App().getMp3(); mp3.on(); }
應該改為
public void startMp3player(){ new App().startMp3(); }
4、對象的任何組件
//手機app public class App { private Light light; private Aircondition aircondition; private Window window; private Curtain curtain; private Mp3player mp3; public App(){ } //在該方法中,可以使用組件mp3的任何方法 public void startMp3(){ mp3.on(); } }