設(shè)計模式解密(5)- 外觀模式(門面模式)
1、簡介
外觀模式提供了一個統(tǒng)一的接口,用來訪問子系統(tǒng)中的一群接口。外觀定義了一個高層接口,讓子系統(tǒng)更容易使用。
使用外觀模式時,我們創(chuàng)建了一個統(tǒng)一的類,用來包裝子系統(tǒng)中一個或多個復(fù)雜的類,客戶端可以直接通過外觀類來調(diào)用內(nèi)部子系統(tǒng)中方法,從而外觀模式讓客戶和子系統(tǒng)之間避免了緊耦合。
外觀模式的目的不是為了給子系統(tǒng)添加新的功能接口,而是為了讓外部減少與子系統(tǒng)內(nèi)多個模塊的交互,松散耦合,從而讓外部能夠更簡單地使用子系統(tǒng)。
外觀模式的本質(zhì)是:封裝交互,簡化調(diào)用。
英文:Facade
類型:結(jié)構(gòu)型模式
2、實例引入
背景:模仿安裝智能家居前后的對比
操作燈光接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package com.designpattern.facade; /** * 類說明 :燈光接口 */ public interface LightI { /** * 開燈 */ public void on(); /** * 關(guān)燈 */ public void off(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package com.designpattern.facade.impl; import com.designpattern.facade.LightI; /** * 類說明 :燈光接口實現(xiàn)類 */ public class Light implements LightI { @Override public void on() { System.out.println( "打開燈" ); } @Override public void off() { System.out.println( "關(guān)閉燈" ); } } |
操作電視接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package com.designpattern.facade; /** * 類說明 :電視接口 */ public interface TVI { /** * 開機(jī) */ public void on(); /** * 關(guān)機(jī) */ public void off(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package com.designpattern.facade.impl; import com.designpattern.facade.TVI; /** * 類說明 :電視接口實現(xiàn)類 */ public class TV implements TVI { @Override public void on() { System.out.println( "打開電視" ); } @Override public void off() { System.out.println( "關(guān)閉電視" ); } } |
在安裝智能家居前:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package com.designpattern.facade; import com.designpattern.facade.impl.Light; import com.designpattern.facade.impl.TV; /** * 類說明 :測試 */ public class Test { public static void main(String[] args) { //----晚上下班回到家---- //開燈光 LightI light = new Light(); light.on(); //看電視 TVI tv = new TV(); tv.on(); //-----睡覺----- //關(guān)燈光 light.off(); //關(guān)電視 tv.off(); } } |
結(jié)果:
1 2 3 4 | 打開燈 打開電視 關(guān)閉燈 關(guān)閉電視 |
我們需要一個一個把需要開的電器打開,是不是好麻煩?
下面咱們引入智能家居
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package com.designpattern.facade; /** * 類說明 :智能家居總開關(guān)接口 */ public interface SmartHomeI { /** * 總開 */ public void on(); /** * 總關(guān) */ public void off(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package com.designpattern.facade.impl; import com.designpattern.facade.LightI; import com.designpattern.facade.SmartHomeI; import com.designpattern.facade.TVI; /** * 類說明 :智能家居總開關(guān)接口 */ public class SmartHome implements SmartHomeI { private LightI light = new Light(); private TVI tv = new TV(); @Override public void on() { light.on(); tv.on(); } @Override public void off() { light.off(); tv.off(); } } |
安裝智能家居以后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package com.designpattern.facade; import com.designpattern.facade.impl.Light; import com.designpattern.facade.impl.SmartHome; import com.designpattern.facade.impl.TV; /** * 類說明 :測試 */ public class Test { public static void main(String[] args) { SmartHomeI smarthome = new SmartHome(); //----晚上下班回到家---- smarthome.on(); //-----睡覺----- smarthome.off(); } } |
結(jié)果:
1 2 3 4 | 打開燈 打開電視 關(guān)閉燈 關(guān)閉電視 |
就一個開關(guān)是不是很方便?
3、解決的問題
從上面的例子看:
外觀模式對客戶屏蔽了子系統(tǒng)組件,從而簡化了接口,減少了客戶處理的對象數(shù)目并使子系統(tǒng)的使用更加簡單。
外觀模式實現(xiàn)了子系統(tǒng)與客戶之間的松耦合關(guān)系,而子系統(tǒng)內(nèi)部的功能組件是緊耦合的,松耦合使得子系統(tǒng)的組件變化不會影響到它的客戶。(比如將來我換一臺電視,只需要修改一下電視接口即可,對外部的智能家居接口不需要修改,從而不影響外部使用者)
4、應(yīng)用場景
需要將設(shè)計進(jìn)行分層時考慮外觀模式;(在層次化結(jié)構(gòu)中,可以使用外觀模式定義系統(tǒng)中每一層的入口,其中三層架構(gòu)就是這樣的一個例子)
在開發(fā)階段,子系統(tǒng)往往因為重構(gòu)變得越來越復(fù)雜,增加外觀模式可以提供一個簡單的接口,減少它們之間的依賴;(外一個復(fù)雜的子系統(tǒng)提供一個簡單的接口)
在維護(hù)一個遺留的大型系統(tǒng)時,可以這個系統(tǒng)已經(jīng)非常難以維護(hù)和擴(kuò)展,可以為新系統(tǒng)開發(fā)一個外觀類,來提供設(shè)計粗糙或高度復(fù)雜的遺留代碼的比較清晰簡單的接口,讓新系統(tǒng)與外觀類交互,外觀模式與遺留代碼交互所有復(fù)雜的工作;(提供子系統(tǒng)的獨立性)
5、優(yōu)缺點
優(yōu)點:
外觀模式降低了客戶端對子系統(tǒng)使用的復(fù)雜性;
外觀模式松散了客戶端與子系統(tǒng)的耦合關(guān)系,讓子系統(tǒng)內(nèi)部的模塊能更容易擴(kuò)展和維護(hù);
通過合理使用外觀模式,可以幫助我們更好的劃分訪問的層次;
使用外觀模式還有一個附帶的好處,就是能夠有選擇性地暴露方法。一個模塊中定義的方法可以分成兩部分,一部分是給子系統(tǒng)外部使用的,一部分是子系統(tǒng)內(nèi)部模塊之間相互調(diào)用時使用的。有了外觀類,那么用于子系統(tǒng)內(nèi)部模塊之間相互調(diào)用的方法就不用暴露給子系統(tǒng)外部了;
缺點:
如果增加新的子系統(tǒng)可能需要修改外觀類或客戶端的源代碼,這樣就違背了”開——閉原則“(不過這點也是不可避免);
6、與其他模式對比
外觀模式與適配器模式非常類似;
外觀模式與適配器模式不同的是:適配器模式是將一個對象包裝起來以改變其接口,而外觀是將一群對象 ”包裝“起來以簡化其接口。它們的意圖是不一樣的,適配器是將接口轉(zhuǎn)換為不同接口,而外觀模式是提供一個統(tǒng)一的接口來簡化接口;
外觀模式旨在:子系統(tǒng)的高層接口;
適配器模式旨在:對象接口的變化;
7、總結(jié)
外觀模式,為子系統(tǒng)的一組接口提供一個統(tǒng)一的接口,該模式定義了一個高層接口,這一個高層接口使的子系統(tǒng)更加容易使用。并且外觀模式可以解決層結(jié)構(gòu)分離、降低系統(tǒng)耦合度和為新舊系統(tǒng)交互提供接口功能。
PS:源碼地址 https://github.com/JsonShare/DesignPattern/tree/master
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!
如果標(biāo)題被標(biāo)記為轉(zhuǎn)載,轉(zhuǎn)載請注明原作者地址,詳見引用
版權(quán)聲明,轉(zhuǎn)載請注明出處:http://www.cnblogs.com/JsonShare
http://www.cnblogs.com/JsonShare/p/7121383.html