前言
行為型模式森缠,共十一種:策略模式拔鹰、模板方法模式、觀(guān)察者模式贵涵、迭代器模式列肢、解釋器模式、責(zé)任鏈模式宾茂、命令模式瓷马、備忘錄模式、狀態(tài)模式跨晴、訪(fǎng)問(wèn)者模式决采、中介者模式。分兩篇文章總結(jié)坟奥,本篇主要涉及到的設(shè)計(jì)模式是:
命令模式树瞭、備忘錄模式、狀態(tài)模式爱谁、訪(fǎng)問(wèn)者模式晒喷、中介者模式
其他同系列的文章還有:
面向?qū)ο缶幊讨械牧笤瓌t
設(shè)計(jì)模式| 創(chuàng)建型模式
設(shè)計(jì)模式| 結(jié)構(gòu)型模式
設(shè)計(jì)模式| 行為型模式 (上)
設(shè)計(jì)模式| 行為型模式 (下)
歡迎閱讀,評(píng)論7玫小A骨谩!
1寺旺、命令模式
請(qǐng)求發(fā)送者與接收者解耦—命令模式
在軟件開(kāi)發(fā)中爷抓,我們經(jīng)常需要向某些對(duì)象發(fā)送請(qǐng)求(調(diào)用其中的某個(gè)或某些方法),
但是并不知道請(qǐng)求的接收者是誰(shuí)阻塑,也不知道被請(qǐng)求的操作是哪個(gè)蓝撇,
此時(shí),我們特別希望能夠以一種松耦合的方式來(lái)設(shè)計(jì)軟件陈莽,使得請(qǐng)求發(fā)送者與請(qǐng)求接收者能夠消除彼此之間的耦合渤昌,
讓對(duì)象之間的調(diào)用關(guān)系更加靈活,可以靈活地指定請(qǐng)求接收者以及被請(qǐng)求的操作走搁。命令模式為此類(lèi)問(wèn)題提供了一個(gè)較為完美的解決方案独柑。
命令模式可以將請(qǐng)求發(fā)送者和接收者完全解耦,發(fā)送者與接收者之間沒(méi)有直接引用關(guān)系私植,發(fā)送請(qǐng)求的對(duì)象只需要知道如何發(fā)送請(qǐng)求忌栅,
而不必知道如何完成請(qǐng)求。
命令模式定義如下:
命令模式(Command Pattern):將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象曲稼,從而讓我們可用不同的請(qǐng)求對(duì)客戶(hù)進(jìn)行參數(shù)化索绪;對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志,以及支持可撤銷(xiāo)的操作躯肌。命令模式是一種對(duì)象行為型模式者春,其別名為動(dòng)作(Action)模式或事務(wù)(Transaction)模式。
命令模式的核心在于引入了命令類(lèi)清女,通過(guò)命令類(lèi)來(lái)降低發(fā)送者和接收者的耦合度钱烟,請(qǐng)求發(fā)送者只需指定一個(gè)命令對(duì)象,再通過(guò)命令對(duì)象來(lái)調(diào)用請(qǐng)求接收者的處理方法嫡丙。
在命令模式結(jié)構(gòu)圖中包含如下幾個(gè)角色:
● Command(抽象命令類(lèi)):抽象命令類(lèi)一般是一個(gè)抽象類(lèi)或接口拴袭,在其中聲明了用于執(zhí)行請(qǐng)求的execute()等方法,
通過(guò)這些方法可以調(diào)用請(qǐng)求接收者的相關(guān)操作曙博。
● ConcreteCommand(具體命令類(lèi)):具體命令類(lèi)是抽象命令類(lèi)的子類(lèi)拥刻,實(shí)現(xiàn)了在抽象命令類(lèi)中聲明的方法,
它對(duì)應(yīng)具體的接收者對(duì)象父泳,將接收者對(duì)象的動(dòng)作綁定其中般哼。在實(shí)現(xiàn)execute()方法時(shí)吴汪,將調(diào)用接收者對(duì)象的相關(guān)操作(Action)。
● Invoker(調(diào)用者):調(diào)用者即請(qǐng)求發(fā)送者蒸眠,它通過(guò)命令對(duì)象來(lái)執(zhí)行請(qǐng)求漾橙。一個(gè)調(diào)用者并不需要在設(shè)計(jì)時(shí)確定其接收者,
因此它只與抽象命令類(lèi)之間存在關(guān)聯(lián)關(guān)系楞卡。在程序運(yùn)行時(shí)可以將一個(gè)具體命令對(duì)象注入其中霜运,再調(diào)用具體命令對(duì)象的execute()方法,
從而實(shí)現(xiàn)間接調(diào)用請(qǐng)求接收者的相關(guān)操作蒋腮。
● Receiver(接收者):接收者執(zhí)行與請(qǐng)求相關(guān)的操作淘捡,它具體實(shí)現(xiàn)對(duì)請(qǐng)求的業(yè)務(wù)處理。
命令模式的本質(zhì)是對(duì)請(qǐng)求進(jìn)行封裝池摧,一個(gè)請(qǐng)求對(duì)應(yīng)于一個(gè)命令焦除,將發(fā)出命令的責(zé)任和執(zhí)行命令的責(zé)任分割開(kāi)。
每一個(gè)命令都是一個(gè)操作:請(qǐng)求的一方發(fā)出請(qǐng)求要求執(zhí)行一個(gè)操作险绘;接收的一方收到請(qǐng)求踢京,并執(zhí)行相應(yīng)的操作。
命令模式允許請(qǐng)求的一方和接收的一方獨(dú)立開(kāi)來(lái)宦棺,使得請(qǐng)求的一方不必知道接收請(qǐng)求的一方的接口瓣距,更不必知道請(qǐng)求如何被接收、操作是否被執(zhí)行代咸、何時(shí)被執(zhí)行蹈丸,以及是怎么被執(zhí)行的。
命令模式的關(guān)鍵在于引入了抽象命令類(lèi)呐芥,請(qǐng)求發(fā)送者針對(duì)抽象命令類(lèi)編程逻杖,只有實(shí)現(xiàn)了抽象命令類(lèi)的具體命令才與請(qǐng)求接收者相關(guān)聯(lián)。
在最簡(jiǎn)單的抽象命令類(lèi)中只包含了一個(gè)抽象的execute()方法思瘟,每個(gè)具體命令類(lèi)將一個(gè)Receiver類(lèi)型的對(duì)象作為一個(gè)實(shí)例變量進(jìn)行存儲(chǔ)荸百,
從而具體指定一個(gè)請(qǐng)求的接收者,不同的具體命令類(lèi)提供了execute()方法的不同實(shí)現(xiàn)滨攻,并調(diào)用不同接收者的請(qǐng)求處理方法够话。
2、備忘錄模式
撤銷(xiāo)功能的實(shí)現(xiàn)—備忘錄模式
我們?cè)诰幊痰臅r(shí)候光绕,經(jīng)常需要保存對(duì)象的中間狀態(tài)女嘲,當(dāng)需要的時(shí)候,可以恢復(fù)到這個(gè)狀態(tài)诞帐。
比如,我們使用Eclipse進(jìn)行編程時(shí)停蕉,假如編寫(xiě)失誤(例如不小心誤刪除了幾行代碼)愕鼓,
我們希望返回刪除前的狀態(tài)钙态,便可以使用Ctrl+Z來(lái)進(jìn)行返回。這時(shí)我們便可以使用備忘錄模式來(lái)實(shí)現(xiàn)拒啰。
備忘錄模式提供了一種狀態(tài)恢復(fù)的實(shí)現(xiàn)機(jī)制驯绎,使得用戶(hù)可以方便地回到一個(gè)特定的歷史步驟,
當(dāng)新的狀態(tài)無(wú)效或者存在問(wèn)題時(shí)谋旦,可以使用暫時(shí)存儲(chǔ)起來(lái)的備忘錄將狀態(tài)復(fù)原,
當(dāng)前很多軟件都提供了撤銷(xiāo)(Undo)操作屈尼,其中就使用了備忘錄模式册着。
備忘錄模式定義如下:
備忘錄模式(Memento Pattern):在不破壞封裝的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài)脾歧,并在該對(duì)象之外保存這個(gè)狀態(tài)甲捏,這樣可以在以后將對(duì)象恢復(fù)到原先保存的狀態(tài)。它是一種對(duì)象行為型模式鞭执,其別名為T(mén)oken司顿。
在備忘錄模式結(jié)構(gòu)圖中包含如下幾個(gè)角色:
● Originator(原發(fā)器):它是一個(gè)普通類(lèi),可以創(chuàng)建一個(gè)備忘錄兄纺,并存儲(chǔ)它的當(dāng)前內(nèi)部狀態(tài)大溜,
也可以使用備忘錄來(lái)恢復(fù)其內(nèi)部狀態(tài),一般將需要保存內(nèi)部狀態(tài)的類(lèi)設(shè)計(jì)為原發(fā)器估脆。
● Memento(備忘錄):存儲(chǔ)原發(fā)器的內(nèi)部狀態(tài)钦奋,根據(jù)原發(fā)器來(lái)決定保存哪些內(nèi)部狀態(tài)。備忘錄的設(shè)計(jì)一般可以參考原發(fā)器的設(shè)計(jì)疙赠,
根據(jù)實(shí)際需要確定備忘錄類(lèi)中的屬性付材。需要注意的是,除了原發(fā)器本身與負(fù)責(zé)人類(lèi)之外圃阳,備忘錄對(duì)象不能直接供其他類(lèi)使用厌衔,
原發(fā)器的設(shè)計(jì)在不同的編程語(yǔ)言中實(shí)現(xiàn)機(jī)制會(huì)有所不同。
● Caretaker(負(fù)責(zé)人):負(fù)責(zé)人又稱(chēng)為管理者捍岳,它負(fù)責(zé)保存?zhèn)渫浉皇伲遣荒軐?duì)備忘錄的內(nèi)容進(jìn)行操作或檢查。
在負(fù)責(zé)人類(lèi)中可以存儲(chǔ)一個(gè)或多個(gè)備忘錄對(duì)象祟同,它只負(fù)責(zé)存儲(chǔ)對(duì)象作喘,而不能修改對(duì)象,也無(wú)須知道對(duì)象的實(shí)現(xiàn)細(xì)節(jié)晕城。
理解備忘錄模式并不難泞坦,但關(guān)鍵在于如何設(shè)計(jì)備忘錄類(lèi)和負(fù)責(zé)人類(lèi)。由于在備忘錄中存儲(chǔ)的是原發(fā)器的中間狀態(tài)砖顷,因此需要防止原發(fā)器以外的其他對(duì)象訪(fǎng)問(wèn)備忘錄贰锁,特別是不允許其他對(duì)象來(lái)修改備忘錄赃梧。
備忘錄模式的優(yōu)缺點(diǎn)和適用場(chǎng)景
備忘錄模式的優(yōu)點(diǎn)有:
1.當(dāng)發(fā)起人角色中的狀態(tài)改變時(shí),有可能這是個(gè)錯(cuò)誤的改變豌熄,我們使用備忘錄模式就可以把這個(gè)錯(cuò)誤的改變還原授嘀。
2. 備份的狀態(tài)是保存在發(fā)起人角色之外的,這樣锣险,發(fā)起人角色就不需要對(duì)各個(gè)備份的狀態(tài)進(jìn)行管理蹄皱。
備忘錄模式的缺點(diǎn):
在實(shí)際應(yīng)用中,備忘錄模式都是多狀態(tài)和多備份的芯肤,發(fā)起人角色的狀態(tài)需要存儲(chǔ)到備忘錄對(duì)象中巷折,對(duì)資源的消耗是比較嚴(yán)重的。
如果有需要提供回滾操作的需求崖咨,使用備忘錄模式非常適合锻拘,比如jdbc的事務(wù)操作,文本編輯器的Ctrl+Z恢復(fù)等击蹲。
3署拟、狀態(tài)模式
處理對(duì)象的多種狀態(tài)及其相互轉(zhuǎn)換-狀態(tài)模式
狀態(tài)模式用于解決系統(tǒng)中復(fù)雜對(duì)象的狀態(tài)轉(zhuǎn)換以及不同狀態(tài)下行為的封裝問(wèn)題。
當(dāng)系統(tǒng)中某個(gè)對(duì)象存在多個(gè)狀態(tài)歌豺,這些狀態(tài)之間可以進(jìn)行轉(zhuǎn)換推穷,而且對(duì)象在不同狀態(tài)下行為不相同時(shí)可以使用狀態(tài)模式。
狀態(tài)模式將一個(gè)對(duì)象的狀態(tài)從該對(duì)象中分離出來(lái)世曾,封裝到專(zhuān)門(mén)的狀態(tài)類(lèi)中缨恒,
使得對(duì)象狀態(tài)可以靈活變化,對(duì)于客戶(hù)端而言轮听,無(wú)須關(guān)心對(duì)象狀態(tài)的轉(zhuǎn)換以及對(duì)象所處的當(dāng)前狀態(tài)骗露,
無(wú)論對(duì)于何種狀態(tài)的對(duì)象,客戶(hù)端都可以一致處理血巍。
狀態(tài)模式定義如下:
狀態(tài)模式(State Pattern):允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為萧锉,對(duì)象看起來(lái)似乎修改了它的類(lèi)。其別名為狀態(tài)對(duì)象(Objects for States)述寡,狀態(tài)模式是一種對(duì)象行為型模式柿隙。
在狀態(tài)模式中引入了抽象狀態(tài)類(lèi)和具體狀態(tài)類(lèi),它們是狀態(tài)模式的核心鲫凶,
在狀態(tài)模式結(jié)構(gòu)圖中包含如下幾個(gè)角色:
● Context(環(huán)境類(lèi)):環(huán)境類(lèi)又稱(chēng)為上下文類(lèi)禀崖,它是擁有多種狀態(tài)的對(duì)象。
由于環(huán)境類(lèi)的狀態(tài)存在多樣性且在不同狀態(tài)下對(duì)象的行為有所不同螟炫,因此將狀態(tài)獨(dú)立出去形成單獨(dú)的狀態(tài)類(lèi)波附。
在環(huán)境類(lèi)中維護(hù)一個(gè)抽象狀態(tài)類(lèi)State的實(shí)例,這個(gè)實(shí)例定義當(dāng)前狀態(tài),在具體實(shí)現(xiàn)時(shí)掸屡,它是一個(gè)State子類(lèi)的對(duì)象封寞。
● State(抽象狀態(tài)類(lèi)):它用于定義一個(gè)接口以封裝與環(huán)境類(lèi)的一個(gè)特定狀態(tài)相關(guān)的行為,
在抽象狀態(tài)類(lèi)中聲明了各種不同狀態(tài)對(duì)應(yīng)的方法仅财,而在其子類(lèi)中實(shí)現(xiàn)類(lèi)這些方法狈究,由于不同狀態(tài)下對(duì)象的行為可能不同,
因此在不同子類(lèi)中方法的實(shí)現(xiàn)可能存在不同盏求,相同的方法可以寫(xiě)在抽象狀態(tài)類(lèi)中抖锥。
● ConcreteState(具體狀態(tài)類(lèi)):它是抽象狀態(tài)類(lèi)的子類(lèi),每一個(gè)子類(lèi)實(shí)現(xiàn)一個(gè)與環(huán)境類(lèi)的一個(gè)狀態(tài)相關(guān)的行為风喇,
每一個(gè)具體狀態(tài)類(lèi)對(duì)應(yīng)環(huán)境的一個(gè)具體狀態(tài)宁改,不同的具體狀態(tài)類(lèi)其行為有所不同。
在狀態(tài)模式中魂莫,我們將對(duì)象在不同狀態(tài)下的行為封裝到不同的狀態(tài)類(lèi)中,為了讓系統(tǒng)具有更好的靈活性和可擴(kuò)展性爹耗,
同時(shí)對(duì)各狀態(tài)下的共有行為進(jìn)行封裝耙考,我們需要對(duì)狀態(tài)進(jìn)行抽象,引入了抽象狀態(tài)類(lèi)角色
在抽象狀態(tài)類(lèi)的子類(lèi)即具體狀態(tài)類(lèi)中實(shí)現(xiàn)了在抽象狀態(tài)類(lèi)中聲明的業(yè)務(wù)方法潭兽,不同的具體狀態(tài)類(lèi)可以提供完全不同的方法實(shí)現(xiàn)倦始,
在實(shí)際使用時(shí),在一個(gè)狀態(tài)類(lèi)中可能包含多個(gè)業(yè)務(wù)方法山卦,如果在具體狀態(tài)類(lèi)中某些業(yè)務(wù)方法的實(shí)現(xiàn)完全相同鞋邑,
可以將這些方法移至抽象狀態(tài)類(lèi),實(shí)現(xiàn)代碼的復(fù)用账蓉。
狀態(tài)模式將一個(gè)對(duì)象在不同狀態(tài)下的不同行為封裝在一個(gè)個(gè)狀態(tài)類(lèi)中枚碗,通過(guò)設(shè)置不同的狀態(tài)對(duì)象可以讓環(huán)境對(duì)象擁有不同的行為,而狀態(tài)轉(zhuǎn)換的細(xì)節(jié)對(duì)于客戶(hù)端而言是透明的铸本,方便了客戶(hù)端的使用肮雨。
在實(shí)際開(kāi)發(fā)中,狀態(tài)模式具有較高的使用頻率箱玷,在工作流和游戲開(kāi)發(fā)中狀態(tài)模式都得到了廣泛的應(yīng)用怨规,
例如公文狀態(tài)的轉(zhuǎn)換、游戲中角色的升級(jí)等锡足。
-
主要優(yōu)點(diǎn)
狀態(tài)模式的主要優(yōu)點(diǎn)如下: (1) 封裝了狀態(tài)的轉(zhuǎn)換規(guī)則波丰,在狀態(tài)模式中可以將狀態(tài)的轉(zhuǎn)換代碼封裝在環(huán)境類(lèi)或者具體狀態(tài)類(lèi)中,可以對(duì)狀態(tài)轉(zhuǎn)換代碼進(jìn)行集中管理 而不是分散在一個(gè)個(gè)業(yè)務(wù)方法中舶得。 (2) 將所有與某個(gè)狀態(tài)有關(guān)的行為放到一個(gè)類(lèi)中掰烟,只需要注入一個(gè)不同的狀態(tài)對(duì)象即可使環(huán)境對(duì)象擁有不同的行為。 (3) 允許狀態(tài)轉(zhuǎn)換邏輯與狀態(tài)對(duì)象合成一體,而不是提供一個(gè)巨大的條件語(yǔ)句塊媚赖, 狀態(tài)模式可以讓我們避免使用龐大的條件語(yǔ)句來(lái)將業(yè)務(wù)方法和狀態(tài)轉(zhuǎn)換代碼交織在一起霜瘪。 (4) 可以讓多個(gè)環(huán)境對(duì)象共享一個(gè)狀態(tài)對(duì)象,從而減少系統(tǒng)中對(duì)象的個(gè)數(shù)惧磺。
-
主要缺點(diǎn)
狀態(tài)模式的主要缺點(diǎn)如下: (1) 狀態(tài)模式的使用必然會(huì)增加系統(tǒng)中類(lèi)和對(duì)象的個(gè)數(shù)颖对,導(dǎo)致系統(tǒng)運(yùn)行開(kāi)銷(xiāo)增大。 (2) 狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)都較為復(fù)雜磨隘,如果使用不當(dāng)將導(dǎo)致程序結(jié)構(gòu)和代碼的混亂缤底,增加系統(tǒng)設(shè)計(jì)的難度。 (3) 狀態(tài)模式對(duì)“開(kāi)閉原則”的支持并不太好番捂,增加新的狀態(tài)類(lèi)需要修改那些負(fù)責(zé)狀態(tài)轉(zhuǎn)換的源代碼个唧, 否則無(wú)法轉(zhuǎn)換到新增狀態(tài);而且修改某個(gè)狀態(tài)類(lèi)的行為也需修改對(duì)應(yīng)類(lèi)的源代碼设预。
-
適用場(chǎng)景
在以下情況下可以考慮使用狀態(tài)模式: (1) 對(duì)象的行為依賴(lài)于它的狀態(tài)(如某些屬性值)徙歼,狀態(tài)的改變將導(dǎo)致行為的變化。 (2) 在代碼中包含大量與對(duì)象狀態(tài)有關(guān)的條件語(yǔ)句鳖枕,這些條件語(yǔ)句的出現(xiàn)魄梯, 會(huì)導(dǎo)致代碼的可維護(hù)性和靈活性變差,不能方便地增加和刪除狀態(tài)宾符,并且導(dǎo)致客戶(hù)類(lèi)與類(lèi)庫(kù)之間的耦合增強(qiáng)酿秸。
4、訪(fǎng)問(wèn)者模式
操作復(fù)雜對(duì)象結(jié)構(gòu)——訪(fǎng)問(wèn)者模式
訪(fǎng)問(wèn)者模式是一種較為復(fù)雜的行為型設(shè)計(jì)模式魏烫,它包含訪(fǎng)問(wèn)者和被訪(fǎng)問(wèn)元素兩個(gè)主要組成部分辣苏,
這些被訪(fǎng)問(wèn)的元素通常具有不同的類(lèi)型,且不同的訪(fǎng)問(wèn)者可以對(duì)它們進(jìn)行不同的訪(fǎng)問(wèn)操作哄褒。例如處方單中的各種藥品信息就是被訪(fǎng)問(wèn)的元素
而劃價(jià)人員和藥房工作人員就是訪(fǎng)問(wèn)者稀蟋。訪(fǎng)問(wèn)者模式使得用戶(hù)可以在不修改現(xiàn)有系統(tǒng)的情況下擴(kuò)展系統(tǒng)的功能,
為這些不同類(lèi)型的元素增加新的操作读处。
在使用訪(fǎng)問(wèn)者模式時(shí)糊治,被訪(fǎng)問(wèn)元素通常不是單獨(dú)存在的,它們存儲(chǔ)在一個(gè)集合中罚舱,這個(gè)集合被稱(chēng)為“對(duì)象結(jié)構(gòu)”井辜,
訪(fǎng)問(wèn)者通過(guò)遍歷對(duì)象結(jié)構(gòu)實(shí)現(xiàn)對(duì)其中存儲(chǔ)的元素的逐個(gè)操作。
訪(fǎng)問(wèn)者模式定義如下:
訪(fǎng)問(wèn)者模式(Visitor Pattern):提供一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作表示管闷,它使我們可以在不改變各元素的類(lèi)的前提下定義作用于這些元素的新操作粥脚。訪(fǎng)問(wèn)者模式是一種對(duì)象行為型模式。
在訪(fǎng)問(wèn)者模式結(jié)構(gòu)圖中包含如下幾個(gè)角色:
● Vistor(抽象訪(fǎng)問(wèn)者):抽象訪(fǎng)問(wèn)者為對(duì)象結(jié)構(gòu)中每一個(gè)具體元素類(lèi)ConcreteElement聲明一個(gè)訪(fǎng)問(wèn)操作包个,
從這個(gè)操作的名稱(chēng)或參數(shù)類(lèi)型可以清楚知道需要訪(fǎng)問(wèn)的具體元素的類(lèi)型刷允,具體訪(fǎng)問(wèn)者需要實(shí)現(xiàn)這些操作方法冤留,定義對(duì)這些元素的訪(fǎng)問(wèn)操作
● ConcreteVisitor(具體訪(fǎng)問(wèn)者):具體訪(fǎng)問(wèn)者實(shí)現(xiàn)了每個(gè)由抽象訪(fǎng)問(wèn)者聲明的操作,每一個(gè)操作用于訪(fǎng)問(wèn)對(duì)象結(jié)構(gòu)中一種類(lèi)型的元素
● Element(抽象元素):抽象元素一般是抽象類(lèi)或者接口树灶,它定義一個(gè)accept()方法纤怒,該方法通常以一個(gè)抽象訪(fǎng)問(wèn)者作為參數(shù)。
● ConcreteElement(具體元素):具體元素實(shí)現(xiàn)了accept()方法天通,在accept()方法中調(diào)用訪(fǎng)問(wèn)者的訪(fǎng)問(wèn)方法以便完成對(duì)
一個(gè)元素的操作泊窘。
● ObjectStructure(對(duì)象結(jié)構(gòu)):對(duì)象結(jié)構(gòu)是一個(gè)元素的集合,它用于存放元素對(duì)象像寒,并且提供了遍歷其內(nèi)部元素的方法烘豹。
它可以結(jié)合組合模式來(lái)實(shí)現(xiàn),也可以是一個(gè)簡(jiǎn)單的集合對(duì)象诺祸,如一個(gè)List對(duì)象或一個(gè)Set對(duì)象携悯。
訪(fǎng)問(wèn)者模式中對(duì)象結(jié)構(gòu)存儲(chǔ)了不同類(lèi)型的元素對(duì)象,以供不同訪(fǎng)問(wèn)者訪(fǎng)問(wèn)筷笨。訪(fǎng)問(wèn)者模式包括兩個(gè)層次結(jié)構(gòu)憔鬼,
一個(gè)是訪(fǎng)問(wèn)者層次結(jié)構(gòu),提供了抽象訪(fǎng)問(wèn)者和具體訪(fǎng)問(wèn)者胃夏,一個(gè)是元素層次結(jié)構(gòu)逊彭,提供了抽象元素和具體元素。
相同的訪(fǎng)問(wèn)者可以以不同的方式訪(fǎng)問(wèn)不同的元素构订,相同的元素可以接受不同訪(fǎng)問(wèn)者以不同訪(fǎng)問(wèn)方式訪(fǎng)問(wèn)。
在訪(fǎng)問(wèn)者模式中避矢,增加新的訪(fǎng)問(wèn)者無(wú)須修改原有系統(tǒng)悼瘾,系統(tǒng)具有較好的可擴(kuò)展性。
在訪(fǎng)問(wèn)者模式中审胸,抽象訪(fǎng)問(wèn)者定義了訪(fǎng)問(wèn)元素對(duì)象的方法亥宿,通常為每一種類(lèi)型的元素對(duì)象都提供一個(gè)訪(fǎng)問(wèn)方法,
而具體訪(fǎng)問(wèn)者可以實(shí)現(xiàn)這些訪(fǎng)問(wèn)方法砂沛。這些訪(fǎng)問(wèn)方法的命名一般有兩種方式:一種是直接在方法名中標(biāo)明待訪(fǎng)問(wèn)元素對(duì)象的具體類(lèi)型烫扼,
如visitElementA(ElementA elementA),還有一種是統(tǒng)一取名為visit()碍庵,通過(guò)參數(shù)類(lèi)型的不同來(lái)定義一系列重載的visit()方法映企。
當(dāng)然,如果所有的訪(fǎng)問(wèn)者對(duì)某一類(lèi)型的元素的訪(fǎng)問(wèn)操作都相同静浴,則可以將操作代碼移到抽象訪(fǎng)問(wèn)者類(lèi)中堰氓,
由于訪(fǎng)問(wèn)者模式的使用條件較為苛刻,本身結(jié)構(gòu)也較為復(fù)雜苹享,因此在實(shí)際應(yīng)用中使用頻率不是特別高双絮。
當(dāng)系統(tǒng)中存在一個(gè)較為復(fù)雜的對(duì)象結(jié)構(gòu),且不同訪(fǎng)問(wèn)者對(duì)其所采取的操作也不相同時(shí),可以考慮使用訪(fǎng)問(wèn)者模式進(jìn)行設(shè)計(jì)囤攀。
在XML文檔解析软免、編譯器的設(shè)計(jì)、復(fù)雜集合對(duì)象的處理等領(lǐng)域訪(fǎng)問(wèn)者模式得到了一定的應(yīng)用焚挠。
1.主要優(yōu)點(diǎn)
訪(fǎng)問(wèn)者模式的主要優(yōu)點(diǎn)如下:
(1) 增加新的訪(fǎng)問(wèn)操作很方便膏萧。使用訪(fǎng)問(wèn)者模式,增加新的訪(fǎng)問(wèn)操作就意味著增加一個(gè)新的具體訪(fǎng)問(wèn)者類(lèi)宣蔚,
實(shí)現(xiàn)簡(jiǎn)單向抢,無(wú)須修改源代碼,符合“開(kāi)閉原則”胚委。
(2) 將有關(guān)元素對(duì)象的訪(fǎng)問(wèn)行為集中到一個(gè)訪(fǎng)問(wèn)者對(duì)象中挟鸠,而不是分散在一個(gè)個(gè)的元素類(lèi)中。類(lèi)的職責(zé)更加清晰亩冬,
有利于對(duì)象結(jié)構(gòu)中元素對(duì)象的復(fù)用艘希,相同的對(duì)象結(jié)構(gòu)可以供多個(gè)不同的訪(fǎng)問(wèn)者訪(fǎng)問(wèn)。
(3) 讓用戶(hù)能夠在不修改現(xiàn)有元素類(lèi)層次結(jié)構(gòu)的情況下硅急,定義作用于該層次結(jié)構(gòu)的操作覆享。
2.主要缺點(diǎn)
訪(fǎng)問(wèn)者模式的主要缺點(diǎn)如下:
(1) 增加新的元素類(lèi)很困難。在訪(fǎng)問(wèn)者模式中营袜,每增加一個(gè)新的元素類(lèi)都意味著要在抽象訪(fǎng)問(wèn)者角色中增加一個(gè)新的抽象操作撒顿,
并在每一個(gè)具體訪(fǎng)問(wèn)者類(lèi)中增加相應(yīng)的具體操作,這違背了“開(kāi)閉原則”的要求荚板。
(2) 破壞封裝凤壁。訪(fǎng)問(wèn)者模式要求訪(fǎng)問(wèn)者對(duì)象訪(fǎng)問(wèn)并調(diào)用每一個(gè)元素對(duì)象的操作,
這意味著元素對(duì)象有時(shí)候必須暴露一些自己的內(nèi)部操作和內(nèi)部狀態(tài)跪另,否則無(wú)法供訪(fǎng)問(wèn)者訪(fǎng)問(wèn)拧抖。
3.適用場(chǎng)景
在以下情況下可以考慮使用訪(fǎng)問(wèn)者模式:
(1) 一個(gè)對(duì)象結(jié)構(gòu)包含多個(gè)類(lèi)型的對(duì)象,希望對(duì)這些對(duì)象實(shí)施一些依賴(lài)其具體類(lèi)型的操作免绿。
在訪(fǎng)問(wèn)者中針對(duì)每一種具體的類(lèi)型都提供了一個(gè)訪(fǎng)問(wèn)操作唧席,不同類(lèi)型的對(duì)象可以有不同的訪(fǎng)問(wèn)操作。
(2) 需要對(duì)一個(gè)對(duì)象結(jié)構(gòu)中的對(duì)象進(jìn)行很多不同的并且不相關(guān)的操作嘲驾,而需要避免讓這些操作“污染”這些對(duì)象的類(lèi)淌哟,
也不希望在增加新操作時(shí)修改這些類(lèi)。訪(fǎng)問(wèn)者模式使得我們可以將相關(guān)的訪(fǎng)問(wèn)操作集中起來(lái)定義在訪(fǎng)問(wèn)者類(lèi)中距淫,
對(duì)象結(jié)構(gòu)可以被多個(gè)不同的訪(fǎng)問(wèn)者類(lèi)所使用绞绒,將對(duì)象本身與對(duì)象的訪(fǎng)問(wèn)操作分離。
(3) 對(duì)象結(jié)構(gòu)中對(duì)象對(duì)應(yīng)的類(lèi)很少改變榕暇,但經(jīng)常需要在此對(duì)象結(jié)構(gòu)上定義新的操作蓬衡。
5喻杈、中介者模式
協(xié)調(diào)多個(gè)對(duì)象之間的交互—中介者模式
如果在一個(gè)系統(tǒng)中對(duì)象之間的聯(lián)系呈現(xiàn)為網(wǎng)狀結(jié)構(gòu),如下圖所示狰晚。
對(duì)象之間存在大量的多對(duì)多聯(lián)系筒饰,將導(dǎo)致系統(tǒng)非常復(fù)雜,這些對(duì)象既會(huì)影響別的對(duì)象壁晒,也會(huì)被別的對(duì)象所影響瓷们,這些對(duì)象稱(chēng)為同事對(duì)象,
它們之間通過(guò)彼此的相互作用實(shí)現(xiàn)系統(tǒng)的行為秒咐。在網(wǎng)狀結(jié)構(gòu)中谬晕,幾乎每個(gè)對(duì)象都需要與其他對(duì)象發(fā)生相互作用,
而這種相互作用表現(xiàn)為一個(gè)對(duì)象與另外一個(gè)對(duì)象的直接耦合携取,這將導(dǎo)致一個(gè)過(guò)度耦合的系統(tǒng)攒钳。
中介者模式可以使對(duì)象之間的關(guān)系數(shù)量急劇減少,通過(guò)引入中介者對(duì)象雷滋,
可以將系統(tǒng)的網(wǎng)狀結(jié)構(gòu)變成以中介者為中心的星形結(jié)構(gòu)不撑,如下圖所示。
在這個(gè)星形結(jié)構(gòu)中晤斩,同事對(duì)象不再直接與另一個(gè)對(duì)象聯(lián)系焕檬,它通過(guò)中介者對(duì)象與另一個(gè)對(duì)象發(fā)生相互作用。
中介者對(duì)象的存在保證了對(duì)象結(jié)構(gòu)上的穩(wěn)定澳泵,也就是說(shuō)实愚,系統(tǒng)的結(jié)構(gòu)不會(huì)因?yàn)樾聦?duì)象的引入帶來(lái)大量的修改工作。
如果在一個(gè)系統(tǒng)中對(duì)象之間存在多對(duì)多的相互關(guān)系兔辅,我們可以將對(duì)象之間的一些交互行為從各個(gè)對(duì)象中分離出來(lái)爆侣,
并集中封裝在一個(gè)中介者對(duì)象中,并由該中介者進(jìn)行統(tǒng)一協(xié)調(diào)幢妄,這樣對(duì)象之間多對(duì)多的復(fù)雜關(guān)系就轉(zhuǎn)化為相對(duì)簡(jiǎn)單的一對(duì)多關(guān)系。
通過(guò)引入中介者來(lái)簡(jiǎn)化對(duì)象之間的復(fù)雜交互茫负,
中介者模式是“迪米特法則”的一個(gè)典型應(yīng)用蕉鸳。
中介者模式定義如下:
中介者模式(Mediator Pattern):用一個(gè)中介對(duì)象(中介者)來(lái)封裝一系列的對(duì)象交互,中介者使各對(duì)象不需要顯式地相互引用忍法,從而使其耦合松散潮尝,而且可以獨(dú)立地改變它們之間的交互。中介者模式又稱(chēng)為調(diào)停者模式饿序,它是一種對(duì)象行為型模式勉失。
在中介者模式中,我們引入了用于協(xié)調(diào)其他對(duì)象/類(lèi)之間相互調(diào)用的中介者類(lèi)原探,
為了讓系統(tǒng)具有更好的靈活性和可擴(kuò)展性乱凿,通常還提供了抽象中介者
在中介者模式結(jié)構(gòu)圖中包含如下幾個(gè)角色:
● Mediator(抽象中介者):它定義一個(gè)接口顽素,該接口用于與各同事對(duì)象之間進(jìn)行通信。
● ConcreteMediator(具體中介者):它是抽象中介者的子類(lèi)徒蟆,通過(guò)協(xié)調(diào)各個(gè)同事對(duì)象來(lái)實(shí)現(xiàn)協(xié)作行為胁出,它維持了對(duì)各個(gè)同事對(duì)象的引用
● Colleague(抽象同事類(lèi)):它定義各個(gè)同事類(lèi)公有的方法,并聲明了一些抽象方法來(lái)供子類(lèi)實(shí)現(xiàn)段审,
同時(shí)它維持了一個(gè)對(duì)抽象中介者類(lèi)的引用全蝶,其子類(lèi)可以通過(guò)該引用來(lái)與中介者通信。
● ConcreteColleague(具體同事類(lèi)):它是抽象同事類(lèi)的子類(lèi)寺枉;每一個(gè)同事對(duì)象在需要和其他同事對(duì)象通信時(shí)抑淫,先與中介者通信,
通過(guò)中介者來(lái)間接完成與其他同事類(lèi)的通信姥闪;在具體同事類(lèi)中實(shí)現(xiàn)了在抽象同事類(lèi)中聲明的抽象方法始苇。
中介者模式的核心在于中介者類(lèi)的引入,在中介者模式中甘畅,中介者類(lèi)承擔(dān)了兩方面的職責(zé):
(1) 中轉(zhuǎn)作用(結(jié)構(gòu)性):通過(guò)中介者提供的中轉(zhuǎn)作用埂蕊,各個(gè)同事對(duì)象就不再需要顯式引用其他同事,
當(dāng)需要和其他同事進(jìn)行通信時(shí)疏唾,可通過(guò)中介者來(lái)實(shí)現(xiàn)間接調(diào)用蓄氧。該中轉(zhuǎn)作用屬于中介者在結(jié)構(gòu)上的支持。
(2) 協(xié)調(diào)作用(行為性):中介者可以更進(jìn)一步的對(duì)同事之間的關(guān)系進(jìn)行封裝槐脏,同事可以一致的和中介者進(jìn)行交互喉童,
而不需要指明中介者需要具體怎么做,中介者根據(jù)封裝在自身內(nèi)部的協(xié)調(diào)邏輯顿天,對(duì)同事的請(qǐng)求進(jìn)行進(jìn)一步處理堂氯,
將同事成員之間的關(guān)系行為進(jìn)行分離和封裝。該協(xié)調(diào)作用屬于中介者在行為上的支持牌废。
中介者模式將一個(gè)網(wǎng)狀的系統(tǒng)結(jié)構(gòu)變成一個(gè)以中介者對(duì)象為中心的星形結(jié)構(gòu)咽白,在這個(gè)星型結(jié)構(gòu)中,使用中介者對(duì)象與其他對(duì)象的一對(duì)多關(guān)系來(lái)取代原有對(duì)象之間的多對(duì)多關(guān)系鸟缕。中介者模式在事件驅(qū)動(dòng)類(lèi)軟件中應(yīng)用較為廣泛晶框,特別是基于GUI(Graphical User Interface,圖形用戶(hù)界面)的應(yīng)用軟件懂从,此外授段,在類(lèi)與類(lèi)之間存在錯(cuò)綜復(fù)雜的關(guān)聯(lián)關(guān)系的系統(tǒng)中,中介者模式都能得到較好的應(yīng)用番甩。
-
主要優(yōu)點(diǎn)
中介者模式的主要優(yōu)點(diǎn)如下: (1) 中介者模式簡(jiǎn)化了對(duì)象之間的交互侵贵,它用中介者和同事的一對(duì)多交互代替了原來(lái)同事之間的多對(duì)多交互卷拘, 一對(duì)多關(guān)系更容易理解爆阶、維護(hù)和擴(kuò)展胰柑,將原本難以理解的網(wǎng)狀結(jié)構(gòu)轉(zhuǎn)換成相對(duì)簡(jiǎn)單的星型結(jié)構(gòu)器仗。 (2) 中介者模式可將各同事對(duì)象解耦。中介者有利于各同事之間的松耦合蔫骂,我們可以獨(dú)立的改變和復(fù)用每一個(gè)同事和中介者么翰, 增加新的中介者和新的同事類(lèi)都比較方便,更好地符合“開(kāi)閉原則”辽旋。 (3) 可以減少子類(lèi)生成浩嫌,中介者將原本分布于多個(gè)對(duì)象間的行為集中在一起,改變這些行為只需生成新的中介者子類(lèi)即可补胚, 這使各個(gè)同事類(lèi)可被重用码耐,無(wú)須對(duì)同事類(lèi)進(jìn)行擴(kuò)展。
-
主要缺點(diǎn)
中介者模式的主要缺點(diǎn)如下: 在具體中介者類(lèi)中包含了大量同事之間的交互細(xì)節(jié)溶其,可能會(huì)導(dǎo)致具體中介者類(lèi)非常復(fù)雜骚腥,使得系統(tǒng)難以維護(hù)。
-
適用場(chǎng)景
在以下情況下可以考慮使用中介者模式: (1) 系統(tǒng)中對(duì)象之間存在復(fù)雜的引用關(guān)系瓶逃,系統(tǒng)結(jié)構(gòu)混亂且難以理解束铭。 (2) 一個(gè)對(duì)象由于引用了其他很多對(duì)象并且直接和這些對(duì)象通信,導(dǎo)致難以復(fù)用該對(duì)象厢绝。 (3) 想通過(guò)一個(gè)中間類(lèi)來(lái)封裝多個(gè)類(lèi)中的行為契沫,而又不想生成太多的子類(lèi)∥艉海可以通過(guò)引入中介者類(lèi)來(lái)實(shí)現(xiàn)懈万, 在中介者中定義對(duì)象交互的公共行為,如果需要改變行為則可以增加新的具體中介者類(lèi)靶病。
持續(xù)更新中......