設計模式 | 外觀模式/門面模式(facade)
定義:
為子系統中的一組介面提供一個一致的介面,此模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。
結構:(書中圖,侵刪)

一個簡潔易用的外觀類
一個複雜的子系統
例項:
書中提到了理財的例子,找理財經理就不用自己研究各種股票債券什麼了;致使我一度腦子裡只想到了房屋中介,感覺跳不出這個框架了。
最後,終於讓我想到了別的例子:有困難找警察。
我們只需要記住“110”這個電話號碼就完事了,具體問題怎麼處理就辛苦警察同志了。
接下來程式碼實現:
package designpattern.facade; public class HandleTrouble { public void call110(String trouble) { System.out.println(trouble); // 模擬接警員處理來電 if (trouble.indexOf("搶劫") > 0 || trouble.indexOf("殺人") > 0) { CriminalPolice criminalPolice = new CriminalPolice(); criminalPolice.handleIt(); } else if (trouble.indexOf("追尾") > 0 || trouble.indexOf("撞車") > 0) { TrafficPolice trafficPolice = new TrafficPolice(); trafficPolice.handleIt(); } else if (trouble.indexOf("起火") > 0 || trouble.indexOf("燒起來") > 0) { System.out.println("轉接火警..."); FirePolice firePolice = new FirePolice(); firePolice.handleIt(); } else { PeoplePolice peoplePolice = new PeoplePolice(); peoplePolice.handleIt(); } } }
複雜的警察子系統:各個部門
package designpattern.facade; public class CriminalPolice { public void handleIt() { System.out.println("刑警出動..."); } }
package designpattern.facade; public class TrafficPolice { public void handleIt() { System.out.println("交警出動..."); } }
package designpattern.facade; public class FirePolice { public void handleIt() { System.out.println("火警出動..."); } }
package designpattern.facade; public class PeoplePolice { public void handleIt() { System.out.println("民警出動..."); } }
客戶端:
package designpattern.facade; public class Client { public static void main(String[] args) { HandleTrouble handleTrouble = new HandleTrouble(); handleTrouble.call110("救命啊,殺人啦,快來人啊~~~~~"); System.out.println("-------------------"); handleTrouble.call110("XX大樓起火了"); System.out.println("-------------------"); handleTrouble.call110("有人打架了,快來人"); System.out.println("-------------------"); } }
輸出結果:
救命啊,殺人啦,快來人啊~~~~~ 刑警出動... ------------------- XX大樓起火了 轉接火警... 火警出動... ------------------- 有人打架了,快來人 民警出動... -------------------
總結:
上面的例子有一點策略模式的影子,不過兩個設計模式的側重點不一樣。
策略模式側重的是將具體演算法和客戶端分離,使得易於擴充套件且演算法之前可以互相替換。
外觀模式側重的是減少各個模組之間的耦合,使程式碼滿足迪米特法則/最少知識法則,使不需要互相通訊的雙方都不必"認識"對方,不需要知道對方的任何細節,甚至可以不知道對方的存在,只需要通過中間方——即這裡所指的外觀類/門面類通訊即可,
這個模式感覺也很常見。像我們去呼叫騰訊阿里的介面的時候都是不知道他們內部是怎麼具體處理的。
書中也說到何時使用外觀模式,下面整理一下:
首先,在設計初期階段,應該要有意識的將不同的兩層分離。(比如我們熟悉的MVC,業務邏輯層就是另外雙方的Facade)
其次,在開發階段,子系統往往因為不斷的重構演化而變得越來越複雜,大多數的模式使用時也都會產生很多很小的類,這本是好事,但是給外部呼叫他們的使用者程式帶來了使用上的困難,增加外觀Facade可以提供一個簡單的介面,減少他們之間的依賴。
第三,在維護一個遺留的大型系統時,可能這個系統已經非常難以維護和擴充套件了,但因為它包含非常重要的功能,新的需求開發必須要依賴於它。此時可以在新系統和老系統之間建立一個外觀Facade類。