外观模式(Facade) - 为系统分层次
程序面試時經常會碰到系統分層的問題.? 要你描述怎樣分層, 分層的好處等.
而Java 有個外觀模式(facade) 正能幫組我們對系統分層次.
一, 外觀模式(Facade) 的定義
所謂外觀模式, 子系統中的一組接口提供1個一致的界面, 此模式定義了1個高層接口, 這個接口使得這1個子系統更加容易使用.
注意, 這里的接口并不是java的interface的意思,? 畢竟我那本教材不是for Java的.
名詞解釋:
子系統:??? 我們可以認為是因為是一組類, 這些類具有類似的功能(方法).
一組接口:?? 子系統中, 每個類都有1個功能類似的方法,? 這些方法的組合就是一些接口.?? 注意這些方法很可能不是繼承自同1個interface,? 甚至這些類沒有任何聯系, 是不同公司發布的產品.
一致的界面:? 1個在子系統之上的類, 這個類對子系統的類以及"一組接口", 進行歸納.
1個高層接口: 上面那個界面的1個方法(), 它能根據條件調用子系統的其中1個類的方法.
其實稍稍有些經驗的程序猿就知道客戶端只需訪問那個"一致的界面" 就ok了.
二, 1個快遞系統例子.
我們知道快遞的運輸方式有很多種.
比如下面的3個類
空運,? 火車運輸, 和船運.
public class AirEx {public void aExpress(){System.out.println("Expressed by plane!");} }
public class TrainEx {public void tExpress(){System.out.println("Expressed by train!");} }
可見, 三個類, 它們之間毫無關聯, 但是它們都有1個功能類似的方法.
我們就可以把這個三個類看成1個子系統了.
好了, 假如這時有1個人(Client)想把1件物品快遞出去了. 那么它應該找那種快遞呢?
假如他要求3天內運到, 那么他只能找空運.
但是如果物品大于100公斤, 他就不會找空運, 因為空運很貴.
也就是說, 每種快遞方法都有些條件限制的.
有時我們會把條件寫在客戶端里.
例如:
int period = 3;int weight = 100;if (period < 5 & weight <= 100){new AirEx().aExpress();}//....我們來列出這種寫法的缺點:
缺點1:
實際上運輸的條件限制很復雜, 包括價格, 時間, 距離, 物品重量, 物品類型(例如電池不能上飛機)等等.
把規則寫在客戶端每1個客戶都必須清楚這些規則?? 這是不可能的.
除非那個客戶是做淘寶的..
缺點2(迪米特法則):
因為客戶能直接找各種運輸工具, 則代表這些方法必須對所有人開放.
違反了Law of Demeter(具體可以參考我上一篇博文).
現實上估計每人會直接找航空公司去空運吧? 航空公司也不會對個人開放運輸業務.
缺點3(緊耦合):
就上面那個實現了,? 一旦某間公司規則修改, 例如國慶期間, 空運費用半價..
那么就必須通知所有客戶了..
程序猿就必須所有客戶端類(客戶端也有很多種)的代碼...? 否則會判斷錯誤.
無層次的UML:
對于上面的例子, 我們假設有3個客戶端類.那么每個客戶端對有可能訪問3種運輸方式,? 那么UML圖看起來就很混亂了:
是不是有一種感覺,
對運輸類的改動都需要很大的成本....
對了, 有人問,? 把規則寫在每1個運輸方式類里面?
則代表客戶什么也不懂, 必須一個一個去問,?? 比如現實上你去先去航空公司問這個炸彈能不能寄, 然后再去鐵路部去問..
這也是不科學的.
三, 對快遞系統使用外觀模式(Facade)
那么對上面的例子如何修改呢.
很簡單, 加上1個界面類就ok了,? 這個類就是快遞公司.
例如現實上, 你要寄一樣物品, 只需找發快遞公司就ok了,? 它會清楚所有的快遞規則.
你只需要列出你的要求(參數),? 快遞公司根據你的參數以及規則自然會幫你選擇空運, 陸運還是船運.?
例如我添加1個類
ExCompany:
public class ExCompany {public void Express(int period, int weight){if (weight <= 100 && period <= 3){new AirEx().aExpress();return;}if (weight <= 1000){new TrainEx().tExpress();return;}new ShipEx().sExpress();} }
這個基面類對, 子系統的一組接口(各種Express方法)進行了整理.
那么客戶端的代碼十分簡介了:
int period = 5;int weight = 100;new ExCompany().Express(period, weight);
我們在看看這種設計模式的優點:
優點1:
客戶無需關心運輸規則, 有需要的話去問快遞公司就ok了.或者你直接把你的需求告訴快遞公司,? 公司會根據規則幫你選擇運輸方式.
IT點來講就是客戶端代碼很簡潔.
優點2(迪米特法則):
子系統的方法可以對外封閉,? 也就是說只讓界面類去訪問就ok了.客戶端甚至沒必要知道子系統的存在.??
現實上你也很可能不關心你的商品是如何運過來的,? 一定時間內能運到就ok了.
優點3(松耦合):
無論運輸方式的算法如何修改, 只需要修改界面類的接口(對應方法)就ok了,? 對客戶端類毫無影響.也就是說這個系統很方便地進行維護和擴展.
有層次的UML:
看起來是不是對系統分了層次, 不同層次之間的類必須通過接口來互相訪問, 它們的關系好像也沒有那么復雜了.
四, 面試層次的問題.
其實上面的UML圖只有兩個層次, 接口是不算的.
實際項目中, 我們一般會將程序分成3層:
1. 數據訪問層? ->? 這些包括了Connection, DB 讀寫的東西
2. 業務邏輯層 ->? 各種業務類
3. 界面表示層? ->? 用戶見到的界面
它們3個層之間會有各種接口來通訊.
至于優缺點, 大家可以按照上面的回答就可以了.
當然, 實際編程中, 如果能完美地實現3個層次并不簡單, 需要很扎實的功力啊.
總結
以上是生活随笔為你收集整理的外观模式(Facade) - 为系统分层次的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 迪米特法则(Law of Demeter
- 下一篇: KVM 安装windows 虚拟机