前面介紹的適配器模式(設計模式讀書筆記-----適配器模式)講的是如何將一個接口轉換成客戶所需要的另一個接口,它的目的在於
解決接口的不兼容性問題。現在這里有這樣一個模式,它的目的在於如何簡化接口,它可以將多個類的復雜的一切隱藏在背后,只顯露
出一個干凈美觀的外觀。
晚上睡覺之前,你總是喜歡看電視,在你進入卧室的時候你需要完成以下幾個步驟:打開電燈、打開空調、放心銀幕(假如你家
有)、打開電視通過這么些繁瑣的步驟后你終於可以看電視了,但是你要睡覺了呢?又要去進行繁瑣的關閉動作。這里你就需要一個外觀
模式了,通過實現一個更加合理的接口外觀類將這些動作都包裝起來,實現一鍵“看電視”、一鍵“關電視”。這就是外觀模式的動機
一、模式定義
所謂外觀模式就是提供一個統一的接口,用來訪問子系統中的一群接口。
外觀模式定義了一個高層接口,讓子系統更容易使用。如下圖,是使用外觀模式后將子系統的使用變得更加簡單。
在引入外觀模式后,客戶只需要與外觀角色打交道,客戶與子系統的復雜關系有外觀角色來實現,從而降低了系統的耦合度。
二、模式結構
外觀模式包含如下兩個角色:
Facade: 外觀角色
SubSystem:子系統角色
三、模式實現
場景就是上面那個“睡覺看電視”的場景。
實例的UML圖
首先是四個組件(電視、電燈、空調、銀幕)
1 public class Television { 2 public void on(){ 3 System.out.println("打開了電視...."); 4 } 5 6 public void off(){ 7 System.out.println("關閉了電視...."); 8 } 9 }
1 public class Light { 2 public void on(){ 3 System.out.println("打開了電燈...."); 4 } 5 6 public void off(){ 7 System.out.println("關閉了電燈...."); 8 } 9 }
1 public class AirCondition { 2 public void on(){ 3 System.out.println("打開了空調...."); 4 } 5 6 public void off(){ 7 System.out.println("關閉了空調...."); 8 } 9 }
1 public class Screen { 2 public void up(){ 3 System.out.println("升起銀幕...."); 4 } 5 6 public void down(){ 7 System.out.println("下降銀幕...."); 8 } 9 }
然后是比較強大、干凈、美觀的外觀
1 public class WatchTvSwtichFacade { 2 Light light; 3 AirCondition ac; 4 Television tv; 5 Screen screen; 6 7 public WatchTvSwtichFacade(Light light,AirCondition ac,Television tv,Screen screen){ 8 this.light = light; 9 this.ac = ac; 10 this.tv = tv; 11 this.screen = screen; 12 } 13 14 public void on(){ 15 light.on(); //首先開燈 16 ac.on(); //然后是打開空調 17 screen.down(); //把銀幕降下來 18 tv.on(); //最后是打開電視 19 } 20 21 public void off(){ 22 tv.off(); //首先關閉電視機 23 screen.up(); //銀幕升上去 24 ac.off(); //空調關閉 25 light.off(); //最后關燈 26 } 27 }
客戶端
1 public class Client { 2 public static void main(String[] args) { 3 //實例化組件 4 Light light = new Light(); 5 Television tv = new Television(); 6 AirCondition ac = new AirCondition(); 7 Screen screen = new Screen(); 8 9 WatchTvSwtichFacade watchTv = new WatchTvSwtichFacade(light, ac, tv, screen); 10 11 watchTv.on(); 12 System.out.println("--------------可以看電視了........."); 13 watchTv.off(); 14 System.out.println("--------------可以睡覺了..........."); 15 } 16 }
運行結果
從上面的使用通過使用外觀模式,客戶可以非常方便的實現比較復雜的功能。
四、模式優缺點
優點
1、引入外觀模式,是客戶對子系統的使用變得簡單了,減少了與子系統的關聯對象,實現了子系統與客戶之間的松耦合關系。
2、只是提供了一個訪問子系統的統一入口,並不影響用戶直接使用子系統類
3、降低了大型軟件系統中的編譯依賴性,並簡化了系統在不同平台之間的移植過程
缺點
1、不能很好地限制客戶使用子系統類,如果對客戶訪問子系統類做太多的限制則減少了可變性和靈活性
2、在不引入抽象外觀類的情況下,增加新的子系統可能需要修改外觀類或客戶端的源代碼,違背了“開閉原則”
五、使用場景
1、當要為一個復雜子系統提供一個簡單接口時可以使用外觀模式。
2、客戶程序與多個子系統之間存在很大的依賴性。引入外觀類將子系統與客戶以及其他子系統解耦,可以提高子系統的獨立性和
可移植性
六、模式總結
1、 外觀模式的主要優點就在於減少了客戶與子系統之間的關聯對象,使用客戶對子系統的使用變得簡單了,也實現了客戶與子
系統之間的松耦合關系。它的缺點就在於違背了“開閉原則”。
2、 如果需要實現一個外觀模式,需要將子系統組合進外觀中,然后將工作委托給子系統執行。