設計模式——外觀模式及在jdk中的應用
轉自 設計模式--外觀模式Facade(結構型)& http://www.cnblogs.com/xrq730/p/4908822.html :
1. 概述
外觀模式,我們通過外觀的包裝,使應用程式只能看到外觀物件,而不會看到具體的細節物件,這樣無疑會降低應用程式的複雜度,並且提高了程式的可維護性。
例子1:一個電源總開關可以控制四盞燈、一個風扇、一臺空調和一臺電視機的啟動和關閉。該電源總開關可以同時控制上述所有電器裝置,電源總開關即為該系統的外觀模式設計。
2. 問題
為了降低複雜性,常常將系統劃分為若干個子系統。但是如何做到各個系統之間的通訊和相互依賴關係達到最小呢?
3. 解決方案
外觀模式:為子系統中的一組介面提供一個一致的介面, Facade模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。引入外觀角色之後,使用者只需要直接與外觀角色互動,使用者與子系統之間的複雜關係由外觀角色來實現,從而降低了系統的耦合度。
4. 適用性
在遇到以下情況使用facade模式:
1) 當你要為一個複雜子系統提供一個簡單介面時。子系統往往因為不斷演化而變得越來越複雜。大多數模式使用時都會產生更多更小的類。
這使得子系統更具可重用性,也更容易對子系統進行定製,但這也給那些不需要定製子系統的使用者帶來一些使用上的困難。facade可以提供一個簡單的預設檢視,
這一檢視對大多數使用者來說已經足夠,而那些需要更多的可定製性的使用者可以越過facade層。
2) 客戶程式與抽象類的實現部分之間存在著很大的依賴性。引入 facade將這個子系統與客戶以及其他的子系統分離,可以提高子系統的獨立性 和可移植性。
3) 當你需要構建一個層次結構的子系統時,使用 facade模式定義子系統中每層的入口點。如果子系統之間是相互依賴的,你可以讓它們僅通過facade進行通訊,從而簡化了它們之間的依賴關係。
5.
結構
6.構建模式的組成
外觀角色(Facade):是模式的核心,他被客戶client角色呼叫,知道各個子系統的功能。同時根據客戶角色已有的需求預訂了幾種功能組合\
子系統角色(Subsystem classes):實現子系統的功能,並處理由Facade物件指派的任務。對子系統而言,facade和client角色是未知的,沒有Facade的任何相關資訊;即沒有指向Facade的例項。
客戶角色(client):呼叫facade角色獲得完成相應的功能。
7. 效果
Facade模式有下面一些優點:
1)對客戶遮蔽子系統元件,減少了客戶處理的物件數目並使得子系統使用起來更加容易。通過引入外觀模式,客戶程式碼將變得很簡單,與之關聯的物件也很少。 2)實現了子系統與客戶之間的鬆耦合關係,這使得子系統的元件變化不會影響到呼叫它的客戶類,只需要調整外觀類即可。 3)降低了大型軟體系統中的編譯依賴性,並簡化了系統在不同平臺之間的移植過程,因為編譯一個子系統一般不需要編譯所有其他的子系統。一個子系統的修改對其他子系統沒有任何影響,而且子系統內部變化也不會影響到外觀物件。 4)只是提供了一個訪問子系統的統一入口,並不影響使用者直接使用子系統類。 Facade模式的缺點 1) 不能很好地限制客戶使用子系統類,如果對客戶訪問子系統類做太多的限制則減少了可變性和靈活性。 2) 在不引入抽象外觀類的情況下,增加新的子系統可能需要修改外觀類或客戶端的原始碼,違背了“開閉原則”。
8. 實現
外觀模式在Java中的應用及解讀
Tomcat中有很多場景都使用到了外觀模式,因為Tomcat中有很多不同的元件,每個元件需要相互通訊,但又不能將自己內部資料過多地暴露給其他元件。用外觀模式隔離資料是個很好的方法,比如Request上使用外觀模式:
比如Servlet,doGet和doPost方法,引數型別是介面HttpServletRequest和介面HttpServletResponse,那麼Tomcat中傳遞過來的真實型別到底是什麼呢?
有過對Java Web專案Debug經驗的肯定會發現,在真正呼叫Servlet前,會經過很多Tomcat方法。反編譯一下javaee.jar包就會看到,傳遞給Tomcat的request和response的真正型別是:
看到返回的都是一個Facade類。因為Request類中很多方法都是元件內部之間互動用的,比如setComet、setReuqestedSessionId等方法,這些方法並不對外公開,但又必須設定為public,因為還要和內部元件互動使用。最好的解決方法就是通過使用一個Facade類,遮蔽掉內部元件之間互動的方法,只提供外部程式要使用的方法。
如果不使用Facade,直接傳遞的是HttpServletRequest和HttpServletResponse,那麼熟悉容器內部運作的開發者可以分別把ServletRequest和ServletResponse向下轉型為HttpServletRequest和HttpServletResponse,這樣就有安全性的問題了。