做會(huì)計(jì)一般關(guān)注什么網(wǎng)站關(guān)鍵詞優(yōu)化推廣
1、簡介
1.1、概述
在軟件開發(fā)中,有時(shí)候?yàn)榱送瓿梢豁?xiàng)較為復(fù)雜的功能,一個(gè)類需要和多個(gè)其他業(yè)務(wù)類交互,而這些需要交互的業(yè)務(wù)類經(jīng)常會(huì)作為一個(gè)完整的整體出現(xiàn),由于涉及的類比較多,導(dǎo)致使用時(shí)代碼較為復(fù)雜。此時(shí),特別需要一個(gè)類似服務(wù)員一樣的角色,由它來負(fù)責(zé)和多個(gè)業(yè)務(wù)類進(jìn)行交互,而使用這些業(yè)務(wù)類的類只需和該類交互即可。外觀模式通過引入一個(gè)新的外觀類來實(shí)現(xiàn)該功能。外觀類充當(dāng)了軟件系統(tǒng)中的“服務(wù)員”,它為多個(gè)業(yè)務(wù)類的調(diào)用提供了一個(gè)統(tǒng)一的入口,簡化了類與類之間的交互。
根據(jù)單一職責(zé)原則,在軟件中將一個(gè)系統(tǒng)劃分為若干個(gè)子系統(tǒng)(Subsystem)有利于降低整個(gè)系統(tǒng)的復(fù)雜性。一個(gè)常見的設(shè)計(jì)目標(biāo)是使客戶類與子系統(tǒng)之間的通信和相互依賴關(guān)系達(dá)到最小,而達(dá)到該目標(biāo)的途徑之一就是引入一個(gè)外觀(Facade)角色,它為子系統(tǒng)的訪問提供了一個(gè)簡單而單一的入口。外觀模式也是迪米特法則的體現(xiàn),通過引入一個(gè)新的外觀角色可以降低原有系統(tǒng)的復(fù)雜度,同時(shí)降低客戶類與子系統(tǒng)類的耦合度。
注:在外觀模式中所指的子系統(tǒng)是一個(gè)廣義的概念,它可以是一個(gè)類、一個(gè)功能模塊、系統(tǒng)的一個(gè)組成部分或者一個(gè)完整的系統(tǒng)。
1.2、定義
外部與一個(gè)子系統(tǒng)的通信通過一個(gè)統(tǒng)一的外觀角色進(jìn)行,為子系統(tǒng)中的一組接口提供一個(gè)一致的入口。外觀模式定義了一個(gè)高層接口,這個(gè)接口使得子系統(tǒng)更加容易使用。外觀模式又稱為門面模式,它是一種對(duì)象結(jié)構(gòu)型模式。
2、解析
外觀模式?jīng)]有一個(gè)一般化的類圖描述,通常使用示意圖來表示外觀模式。
2.1、結(jié)構(gòu)圖
可以看出,在外觀模式結(jié)構(gòu)圖中包含以下兩個(gè)角色。
- Facade(外觀角色):在客戶端可以調(diào)用這個(gè)角色的方法,在外觀角色中可以知道相關(guān)的(一個(gè)或者多個(gè))子系統(tǒng)的功能和責(zé)任。在正常情況下,它將所有從客戶端發(fā)來的請(qǐng)求委派到相應(yīng)的子系統(tǒng)中去,傳遞給相應(yīng)的子系統(tǒng)對(duì)象處理。
- SubSystem(子系統(tǒng)角色):在軟件系統(tǒng)中可以有一個(gè)或者多個(gè)子系統(tǒng)角色。每個(gè)子系統(tǒng)可以不是一個(gè)單獨(dú)的類,而是一個(gè)類的集合,它實(shí)現(xiàn)子系統(tǒng)的功能。每個(gè)子系統(tǒng)都可以被客戶端直接調(diào)用,或者被外觀角色調(diào)用,它處理由外觀類傳過來的請(qǐng)求。子系統(tǒng)并不知道外觀的存在,對(duì)于子系統(tǒng)而言,外觀角色僅僅是另外一個(gè)客戶端而已。
外觀模式的主要目的在于降低系統(tǒng)的復(fù)雜程度。在面向?qū)ο筌浖到y(tǒng)中,類與類之間的關(guān)系越多,并不能表示系統(tǒng)設(shè)計(jì)得越好,反而表示系統(tǒng)中類之間的耦合度太大,這樣的系統(tǒng)在維護(hù)和修改時(shí)都缺乏靈活性,因?yàn)橐粋€(gè)類的改動(dòng)會(huì)導(dǎo)致多個(gè)類發(fā)生變化。而外觀模式的引入很大程度上降低了類之間的通信和關(guān)系。引入外觀模式之后,增加新的子系統(tǒng)或者移除子系統(tǒng)都非常方便,客戶端類無須進(jìn)行修改(或者極少的修改),只需要在外觀類中增加或移除對(duì)子系統(tǒng)的引用即可。從這一點(diǎn)來說,外觀模式在一定程度上并不符合開閉原則,增加新的子系統(tǒng)需要對(duì)原有系統(tǒng)進(jìn)行一定的修改,雖然這個(gè)修改工作量不大。
2.2、代碼示例
外觀模式的另一個(gè)特點(diǎn)是給客戶端的使用帶來極大方便,在外觀角色中存在如下典型代碼:
class Facade{private SystemA obj1=new SystemA;private SystemB obj2=new SystemB;private SystemC obj3=new SystemC;public void method(){obj1.methodA();obj2.methodB();obj3.methodC();}
}
在外觀角色中維持了對(duì)子系統(tǒng)對(duì)象的引用,客戶端可以通過外觀角色來間接調(diào)用子系統(tǒng)對(duì)象的業(yè)務(wù)方法,而無須與子系統(tǒng)對(duì)象直接交互。
2.3、抽象外觀類的引入
在標(biāo)準(zhǔn)的外觀模式結(jié)構(gòu)圖中,如果需要增加、刪除或更換與外觀類交互的子系統(tǒng)類,必須修改外觀類或客戶端的源代碼,這將違背開閉原則。因此,可以通過引入抽象外觀類來對(duì)系統(tǒng)進(jìn)行改進(jìn),在一定程度上解決該問題。在引入抽象外觀類之后,客戶端可以針對(duì)抽象外觀類進(jìn)行編程,對(duì)于新的業(yè)務(wù)需求,不需要修改原有外觀類,而對(duì)應(yīng)增加一個(gè)新的具體外觀類。由新的具體外觀類來關(guān)聯(lián)新的子系統(tǒng)對(duì)象,同時(shí)通過修改配置文件來達(dá)到不修改任何源代碼并更換外觀類的目的。
2.4、外觀角色設(shè)計(jì)補(bǔ)充說明
在實(shí)際應(yīng)用中具體使用外觀模式時(shí),可以參考以下3條關(guān)于外觀角色設(shè)計(jì)的補(bǔ)充說明。
- 在很多情況下為了節(jié)約系統(tǒng)資源,系統(tǒng)中只需要一個(gè)外觀類的實(shí)例。換言之,外觀類可以是一個(gè)單例類。因此可以通過單例模式來設(shè)計(jì)外觀類,從而確保系統(tǒng)中只有唯一一個(gè)訪問子系統(tǒng)的入口,并降低對(duì)系統(tǒng)資源的消耗。引入單例模式的外觀模式結(jié)構(gòu)如下圖所示。
Facade類被設(shè)計(jì)為單例類。在其中定義了一個(gè)靜態(tài)的Facade類型的成員變量instance,其構(gòu)造函數(shù)為私有(private),且通過一個(gè)靜態(tài)的公有工廠方法getInstance()返回自己的唯一實(shí)例。當(dāng)然,能夠設(shè)計(jì)為單例類的外觀類一定是具體外觀類,而不是抽象外觀類。 - 在一個(gè)系統(tǒng)中可以設(shè)計(jì)多個(gè)外觀類,每個(gè)外觀類都負(fù)責(zé)和一些特定的子系統(tǒng)交互,向客戶端提供相應(yīng)的業(yè)務(wù)功能。
- 試圖通過外觀類為子系統(tǒng)增加新行為的做法是錯(cuò)誤的。外觀模式的用意是為子系統(tǒng)提供一個(gè)集中化和簡化的溝通渠道,而不是向子系統(tǒng)加入新行為。新行為的增加應(yīng)該通過修改原有子系統(tǒng)類或增加新的子系統(tǒng)類來實(shí)現(xiàn),不能通過外觀類來實(shí)現(xiàn)。
3、外觀模式總結(jié)
外觀模式是一種使用頻率非常高的設(shè)計(jì)模式,它通過引入一個(gè)外觀角色來簡化客戶端與子系統(tǒng)之間的交互,為復(fù)雜的子系統(tǒng)調(diào)用提供一個(gè)統(tǒng)一的入口,使子系統(tǒng)與客戶端的耦合度降低,且客戶端調(diào)用非常方便。外觀模式并不給系統(tǒng)增加任何新功能,它僅僅是簡化調(diào)用接口。在幾乎所有的軟件中都能夠找到外觀模式的應(yīng)用,例如,絕大多數(shù)B/S系統(tǒng)都有一個(gè)首頁或者導(dǎo)航頁面,大部分C/S系統(tǒng)都提供了菜單或者工具欄。在這里,首頁和導(dǎo)航頁面就是B/S系統(tǒng)的外觀角色,而菜單和工具欄就是C/S系統(tǒng)的外觀角色,通過它們,用戶可以快速訪問子系統(tǒng),降低了系統(tǒng)的復(fù)雜程度。此外,所有涉及與多個(gè)業(yè)務(wù)對(duì)象交互的場(chǎng)景都可以考慮使用外觀模式進(jìn)行重構(gòu),例如Java EE中的Session外觀模式。
3.1、主要優(yōu)點(diǎn)
- 對(duì)客戶端屏蔽了子系統(tǒng)組件,減少了客戶端所需處理的對(duì)象數(shù)目并使得子系統(tǒng)使用起來更加容易。通過引入外觀模式,客戶端代碼將變得很簡單,與之關(guān)聯(lián)的對(duì)象也很少。
- 實(shí)現(xiàn)了子系統(tǒng)與客戶端之間的松耦合關(guān)系,這使得子系統(tǒng)的變化不會(huì)影響到調(diào)用它的客戶端,只需要調(diào)整外觀類即可。
- 一個(gè)子系統(tǒng)的修改對(duì)其他子系統(tǒng)沒有任何影響,而且子系統(tǒng)內(nèi)部變化也不會(huì)影響到外觀對(duì)象。
- 只是提供了一個(gè)訪問子系統(tǒng)的統(tǒng)一入口,并不影響客戶端直接使用子系統(tǒng)類。
3.2、主要缺點(diǎn)
- 不能很好地限制客戶端直接使用子系統(tǒng)類,如果對(duì)客戶端訪問子系統(tǒng)類做太多的限制則減少了可變性和靈活性。
- 如果設(shè)計(jì)不當(dāng),增加新的子系統(tǒng)可能需要修改外觀類的源代碼,這違背了開閉原則。
3.3、適用場(chǎng)景
- 當(dāng)要為訪問一系列復(fù)雜的子系統(tǒng)提供一個(gè)簡單入口時(shí)可以使用外觀模式。
- 客戶端程序與多個(gè)子系統(tǒng)之間存在很大的依賴性。引入外觀類可以將子系統(tǒng)與客戶端解耦,從而提高子系統(tǒng)的獨(dú)立性和可移植性。
- 在層次化結(jié)構(gòu)中,可以使用外觀模式定義系統(tǒng)中每一層的入口,層與層之間不直接產(chǎn)生聯(lián)系,而通過外觀類建立聯(lián)系,降低層之間的耦合度。