|
耦合與變化
耦合是軟件不能抵御變化災(zāi)難的根本性原因。不僅實(shí)體對(duì)象與實(shí)體對(duì)象之間存在耦合關(guān)系,實(shí)體對(duì)象與行為操作之間也存在耦合關(guān)系。
創(chuàng)建型設(shè)計(jì)模式解決的創(chuàng)建者和被創(chuàng)建對(duì)象的耦合問(wèn)題;
結(jié)構(gòu)型設(shè)計(jì)模式解決的是實(shí)體對(duì)象和實(shí)體對(duì)象的耦合問(wèn)題;
行為型設(shè)計(jì)模式解決的是實(shí)體對(duì)象和行為操作之間的耦合問(wèn)題。
動(dòng)機(jī)(Motivation)
在軟件構(gòu)建過(guò)程中,“行為請(qǐng)求者”與“行為實(shí)現(xiàn)者”通常呈現(xiàn)一種“緊耦合”。但在某些場(chǎng)合——比如需要對(duì)行為進(jìn)行“記錄、撤銷/重做(undo/redo)、事務(wù)”等處理,這種無(wú)法抵御變化的緊耦合是不合適的。在這種情況下,如何將“行為請(qǐng)求者”與“行為實(shí)現(xiàn)者”解耦?將一組行為抽象為對(duì)象,可以實(shí)現(xiàn)二者之間的松耦合。
意圖(Intent)
將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而使你可用不同的請(qǐng)求對(duì)客戶(客戶程序,也是行為的請(qǐng)求者)進(jìn)行參數(shù)化;對(duì)請(qǐng)求排隊(duì)或記錄請(qǐng)求日志,以及支持可撤銷的操作。
——《設(shè)計(jì)模式》GoF
例說(shuō)Command應(yīng)用
這種寫法一般情況是沒(méi)有問(wèn)題,但是現(xiàn)在假設(shè)我們需要將這個(gè)操作進(jìn)行日志記錄或者是增加撤銷方法,我們就沒(méi)辦法集中地來(lái)處理。Command模式并不是對(duì)Document類或Graphics類進(jìn)行抽象,而是對(duì)他們里面的Show方法進(jìn)行抽象。
這里Command既可以是抽象類,也可以是接口,其實(shí)寫成接口更好一點(diǎn),因?yàn)镃#支持接口的多繼承,而且Command里面的方法一般是不會(huì)有默認(rèn)實(shí)現(xiàn)。這里具體類的Show方法寫成virtual的好處是它的子類可以重寫Show方法。
客戶程序
對(duì)于這種設(shè)計(jì),還有一點(diǎn)小小的問(wèn)題,我們不能要求所有的類都必須去實(shí)現(xiàn)Command接口。而且這些繼承自Command的類違背了單一職責(zé)原則,它既扮演了行為對(duì)象的角色,又扮演了實(shí)體的實(shí)現(xiàn)者的角色。因此我們做了一些改進(jìn)。
現(xiàn)在我們已經(jīng)把DocumentCommand當(dāng)成一個(gè)行為對(duì)象來(lái)使用了。客戶程序不變。本來(lái)Application和Show是直接依賴的,現(xiàn)在通過(guò)一步一步改進(jìn),Application不依賴于任何Document里面的Show方法,它依賴于Command這個(gè)公有的抽象,Command的繼承類才和Document的方法發(fā)生依賴。
結(jié)構(gòu)(Structure)
其中ConcreteCommand對(duì)應(yīng)例子中的DocumentCommand、GraphicsCommand。Receiver對(duì)應(yīng)Document、Graphics。Action方法不必和Command接口的Execute保持一致。Receiver可以和Command沒(méi)有太大關(guān)系,我們只不過(guò)用ConcreteCommand來(lái)表達(dá)Receiver中的某些行為需求。
Command模式的幾個(gè)要點(diǎn)
Command模式的根本目的在于將“行為請(qǐng)求者”與“行為實(shí)現(xiàn)者”解耦,在面向?qū)ο笳Z(yǔ)言中,常見的實(shí)現(xiàn)手段是“將行為抽象為對(duì)象”。實(shí)現(xiàn)Command接口的具體命令對(duì)象ConcreteCommand有時(shí)候根據(jù)需要可能會(huì)保存一些額外的狀態(tài)信息。
通過(guò)使用Composite模式,可以將多個(gè)“命令”封裝為一個(gè)“復(fù)合命令”MacroCommand。
Command模式與C#中的Delegate(Delegate是把函數(shù)指針抽象成了為一種可被調(diào)用的行為對(duì)象)有些類似。但兩者定義行為接口的規(guī)范有所區(qū)別:Command以面向?qū)ο笾械?ldquo;接口-實(shí)現(xiàn)”來(lái)定義行為接口規(guī)范,更嚴(yán)格,更符合抽象原則;Delegate以函數(shù)簽名來(lái)定義行為接口規(guī)范,更靈活,但抽象能力比較弱。
.NET架構(gòu)中的Command
由于.NET有了Delegate,它很少很少用到Command。它只要需要用到行為抽象,它都用Delegate去做。因?yàn)檫@是Framework,這是和業(yè)務(wù)領(lǐng)域相關(guān)度不大的基礎(chǔ)建設(shè)層面,它是不太需要用到OO的層面。對(duì)于我們來(lái)說(shuō),我們建議更多地用Command去實(shí)現(xiàn)。
it知識(shí)庫(kù):C#面向?qū)ο笤O(shè)計(jì)模式縱橫談:Command 命令模式,轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。