key words: 門(mén)面模式 facade模式
一、
引子
門(mén)面模式是非常簡(jiǎn)單的設(shè)計(jì)模式。
?
二、
定義與結(jié)構(gòu)
門(mén)面模式(
facade
)又稱外觀模式。
GOF
在《設(shè)計(jì)模式》一書(shū)中給出如下定義:為子系統(tǒng)中的一組接口提供一個(gè)一致的界面,
Facade
模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。
定義中提到的子系統(tǒng)是指在設(shè)計(jì)中為了降低復(fù)雜性根據(jù)一定的規(guī)則(比如業(yè)務(wù)、功能),對(duì)系統(tǒng)進(jìn)行的劃分。子系統(tǒng)中封裝有一些類(lèi)。客戶程序在使用子系統(tǒng)的時(shí)候,可能會(huì)像下圖一樣零亂。
在上面的實(shí)現(xiàn)方法中,客戶類(lèi)緊緊地依賴在子系統(tǒng)的實(shí)現(xiàn)上。子系統(tǒng)發(fā)生的變化,很可能要影響到客戶類(lèi)的調(diào)用。而且子系統(tǒng)在不斷優(yōu)化、可重用化的重構(gòu)路上,會(huì)產(chǎn)生更多更小的類(lèi)。這對(duì)使用子系統(tǒng)的客戶類(lèi)來(lái)說(shuō)要完成一個(gè)工作流程,似乎要記住的接口太多了。
門(mén)面模式就是為了解決這種問(wèn)題而產(chǎn)生的。看看使用了門(mén)面模式后的圖:
這樣就減少了客戶程序和子系統(tǒng)之間的耦合,增加了可維護(hù)性。
很明顯,門(mén)面模式有三個(gè)角色組成:
1)
???????
門(mén)面角色(
facade
):這是門(mén)面模式的核心。它被客戶角色調(diào)用,因此它熟悉子系統(tǒng)的功能。它內(nèi)部根據(jù)客戶角色已有的需求預(yù)定了幾種功能組合。
2)
???????
子系統(tǒng)角色:實(shí)現(xiàn)了子系統(tǒng)的功能。對(duì)它而言,
fa?ade
角色就和客戶角色一樣是未知的,它沒(méi)有任何
fa?ade
角色的信息和鏈接。
3)
???????
客戶角色:調(diào)用
fa?ade
角色來(lái)完成要得到的功能。
?
?
?
?
三、
舉例
Facade
一個(gè)典型應(yīng)用就是進(jìn)行數(shù)據(jù)庫(kù)連接。一般我們?cè)诿恳淮螌?duì)數(shù)據(jù)庫(kù)進(jìn)行訪問(wèn),都要進(jìn)行以下操作:先得到
connect
實(shí)例,然后打開(kāi)
connect
獲得連接,得到一個(gè)
statement
,執(zhí)行
sql
語(yǔ)句進(jìn)行查詢,得到查詢結(jié)果集。
??????
我們可以將這些步驟提取出來(lái),封裝在一個(gè)類(lèi)里面。這樣,每次執(zhí)行數(shù)據(jù)庫(kù)訪問(wèn)只需要將必要的參數(shù)傳遞到這個(gè)類(lèi)中就可以了。
??????
有興趣可以在你正在進(jìn)行的系統(tǒng)中實(shí)現(xiàn)一下。
?
?
?
?
四、
使用環(huán)境和優(yōu)點(diǎn)
《設(shè)計(jì)模式》給出了門(mén)面模式的使用環(huán)境:
1)
???????
當(dāng)你要為一個(gè)復(fù)雜子系統(tǒng)提供一個(gè)簡(jiǎn)單接口時(shí)。在上面已經(jīng)描述了原因。
2)
???????
客戶程序與抽象類(lèi)的實(shí)現(xiàn)部分之間存在著很大的依賴性。引入
facade
將這個(gè)子系統(tǒng)與客戶以及其他的子系統(tǒng)分離,可以提高子系統(tǒng)的獨(dú)立性和可移植性(上面也提到了)。
3)
???????
當(dāng)你需要構(gòu)建一個(gè)層次結(jié)構(gòu)的子系統(tǒng)時(shí),使用
facade
模式定義子系統(tǒng)中每層的入口點(diǎn)。如果子系統(tǒng)之間是相互依賴的,你可以讓它們僅通過(guò)
facade
進(jìn)行通訊,從而簡(jiǎn)化了它們之間的依賴關(guān)系。
以下是它的優(yōu)點(diǎn):
1)
???????
它對(duì)客戶屏蔽子系統(tǒng)組件,因而減少了客戶處理的對(duì)象的數(shù)目并使得子系統(tǒng)使用起來(lái)更加方便。
2)
???????
它實(shí)現(xiàn)了子系統(tǒng)與客戶之間的松耦合關(guān)系,而子系統(tǒng)內(nèi)部的功能組件往往是緊耦合的。松耦合關(guān)系使得子系統(tǒng)的組件變化不會(huì)影響到它的客戶。
Facade
模式有助于建立層次結(jié)構(gòu)系統(tǒng),也有助于對(duì)對(duì)象之間的依賴關(guān)系分層。
Facade
模式可以消除復(fù)雜的循環(huán)依賴關(guān)系。這一點(diǎn)在客戶程序與子系統(tǒng)是分別實(shí)現(xiàn)的時(shí)候尤為重要。在大型軟件系統(tǒng)中降低編譯依賴性至關(guān)重要。在子系統(tǒng)類(lèi)改變時(shí),希望盡量減少重編譯工作以節(jié)省時(shí)間。用
Facade
可以降低編譯依賴性,限制重要系統(tǒng)中較小的變化所需的重編譯工作。
Facade
模式同樣也有利于簡(jiǎn)化系統(tǒng)在不同平臺(tái)之間的移植過(guò)程,因?yàn)榫幾g一個(gè)子系統(tǒng)一般不需要編譯所有其他的子系統(tǒng)。
3)
???????
如果應(yīng)用需要,它并不限制它們使用子系統(tǒng)類(lèi)。因此你可以讓客戶程序在系統(tǒng)易用性和通用性之間加以選擇。
?
?
?
五、
java
中的門(mén)面模式
先來(lái)想想門(mén)面模式和我們已經(jīng)講過(guò)的哪個(gè)模式相像?答案就是
抽象工廠
模式
。兩者雖然在分類(lèi)上有所區(qū)別,但是都是為了方便客戶程序的使用而建立。兩者的不同應(yīng)該在于門(mén)面模式不僅方便了客戶的使用,而且隱藏了不該讓客戶知道的類(lèi)(這些類(lèi)僅僅為子系統(tǒng)的其他類(lèi)服務(wù))。
但是在
java
語(yǔ)言中提供的包的概念已經(jīng)能夠很好的解決上面門(mén)面模式提到的問(wèn)題。你可以把一個(gè)子系統(tǒng)放在一個(gè)包里面,里面要提供給外面訪問(wèn)的類(lèi)定義為
public
,而不該公布的類(lèi)就可以設(shè)計(jì)為非
public
。
因此,在一定程度上,門(mén)面模式在
java
中基本上可以不使用了。
標(biāo)準(zhǔn)的門(mén)面模式雖然可以不再使用,但是這種提供一個(gè)中間類(lèi)或者中間方法來(lái)方便客戶程序使用的思想應(yīng)該值得我們來(lái)實(shí)踐的
?
?
?
?
六、
總結(jié)
?
門(mén)面模式從整體來(lái)看,給我的感覺(jué)是,它對(duì)于使兩層之間的調(diào)用粗顆粒化很有幫助,避免了大量細(xì)顆粒度的訪問(wèn)。這和
SOA
中的一些觀點(diǎn)是相同的。
???門(mén)面模式大體介紹完了。請(qǐng)指正:)
門(mén)面模式從整體來(lái)看,給我的感覺(jué)是,它對(duì)于使兩層之間的調(diào)用粗顆粒化很有幫助,避免了大量細(xì)顆粒度的訪問(wèn)。這和
SOA
中的一些觀點(diǎn)是相同的。
???門(mén)面模式大體介紹完了。請(qǐng)指正:)