1. 程式人生 > >設計模式——外觀模式及在jdk中的應用

設計模式——外觀模式及在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,這樣就有安全性的問題了。