欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

.Net行為型設(shè)計模式之命令模式(Command)

 更新時間:2022年05月26日 09:20:36   作者:springsnow  
這篇文章介紹了.Net行為型設(shè)計模式之命令模式(Command),文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

一、動機(jī)(Motivate)

在我們的現(xiàn)實生活中有很多例子可以拿來說明這個模式,我們還拿吃餃子這個事情來說。我的奶奶說了,今天想吃餃子,發(fā)出了命令,然后我奶奶就去看電視去了。我們夫妻倆收到命令就開始和面,做餃子餡,包餃子。餃子包好了,我們就休息一會,等下午5點就開始燒水煮餃子了,晚飯的時間到了,我奶奶按時吃上了餃子。還有很多例子,就不一一列舉了。

在軟件構(gòu)建過程中,“行為請求者”與“行為實現(xiàn)者”通常呈現(xiàn)一種“緊耦合”。但在某些場合——比如需要對行為進(jìn)行“記錄、撤銷/重做(undo/redo)、事務(wù)”等處理,這種無法抵御變化的緊耦合是不合適的。在這種情況下,如何將“行為請求者”與“行為實現(xiàn)者”解耦?將一組行為抽象為對象,可以實現(xiàn)二者之間的松耦合。

二、意圖(Intent)

將一個請求封裝為一個對象,從而使你可用不同的請求對客戶(客戶程序,也是行為的請求者)進(jìn)行參數(shù)化;對請求排隊或記錄請求日志,以及支持可撤銷的操作。                                 ——《設(shè)計模式》GoF

三、結(jié)構(gòu)圖(Structure)

四、模式的組成

從命令模式的結(jié)構(gòu)圖可以看出,它涉及到五個角色,它們分別是:
(1)、客戶角色(Client):創(chuàng)建具體的命令對象,并且設(shè)置命令對象的接收者。注意這個不是我們常規(guī)意義上的客戶端,而是在組裝命令對象和接收者,或許,把這個Client稱為裝配者會更好理解,因為真正使用命令的客戶端是從Invoker來觸發(fā)執(zhí)行。
(2)、命令角色(Command):聲明了一個給所有具體命令類實現(xiàn)的抽象接口。
(3)、具體命令角色(ConcreteCommand):命令接口實現(xiàn)對象,是“虛”的實現(xiàn);通常會持有接收者,并調(diào)用接收者的功能來完成命令要執(zhí)行的操作。
(4)、請求者角色(Invoker):要求命令對象執(zhí)行請求,通常會持有命令對象,可以持有很多的命令對象。這個是客戶端真正觸發(fā)命令并要求命令執(zhí)行相應(yīng)操作的地方,也就是說相當(dāng)于使用命令對象的入口。
(5)、接受者角色(Receiver):接收者,真正執(zhí)行命令的對象。任何類都可能成為一個接收者,只要它能夠?qū)崿F(xiàn)命令要求實現(xiàn)的相應(yīng)功能。

五、命令模式的代碼實現(xiàn)

下面以生活中吃餃子為例來說說如何實現(xiàn)命令模式吧。今天早上,我奶奶就發(fā)布了命令,說她老人家想吃豬肉大蔥餡的餃子。我奶奶腿腳不好,就讓我爸爸捎個話給我們夫妻倆,晚上要吃豬肉大蔥餡的餃子。我瞬間就明白了,這個偉大的任務(wù)就落到我們夫妻倆肩上了。說做就做,保證晚飯能吃上熱氣騰騰的餃子,具體實現(xiàn)代碼如下:

static void Main(string[] args)
{
    //奶奶想吃豬肉大蔥餡的餃子
    PatrickLiuAndWife liuAndLai = new PatrickLiuAndWife();//命令接受者
    Command command = new MakeDumplingsCommand(liuAndLai);//命令
    PaPaInvoker papa = new PaPaInvoker(command); //命令請求者

    //奶奶發(fā)布命令
    papa.ExecuteCommand();

    //奶奶說不想吃餃子了
    papa.Undo();
}

//這個類型就是請求者角色--也就是我爸爸的角色,告訴奶奶要吃餃子
public sealed class PaPaInvoker
{
    //我爸爸從奶奶那里接受到的命令
    private Command _command;

    //爸爸開始接受具體的命令
    public PaPaInvoker(Command command)
    {
        this._command = command;
    }

    //爸爸給我們下達(dá)命令
    public void ExecuteCommand()
    {
        _command.MakeDumplings();
    }

    public void Undo()
    {
        _command.UndoMakeDumplings();
    }
}

//該類型就是抽象命令角色--Commmand,定義了命令的抽象接口,任務(wù)是包餃子
public abstract class Command
{
    //真正任務(wù)的接受者
    protected PatrickLiuAndWife _worker;

    protected Command(PatrickLiuAndWife worker)
    {
        _worker = worker;
    }

    //該方法就是抽象命令對象Command的Execute方法
    public abstract void MakeDumplings();
    public abstract void UndoMakeDumplings();

}

//該類型是具體命令角色--ConcreteCommand,這個命令完成制作“豬肉大蔥餡”的餃子
public sealed class MakeDumplingsCommand : Command
{
    public MakeDumplingsCommand(PatrickLiuAndWife worker) : base(worker) { }

    //執(zhí)行命令--包餃子
    public override void MakeDumplings()
    {
        //執(zhí)行命令---包餃子
        _worker.Execute("今天包的是農(nóng)家豬肉和農(nóng)家大蔥餡的餃子");
    }
    public override void UndoMakeDumplings()
    {
        //執(zhí)行命令---撤銷包餃子
        _worker.Execute("撤銷包餃子");
    }
}

//該類型是具體命令接受角色Receiver,具體包餃子的行為是我們夫妻倆來完成的
public sealed class PatrickLiuAndWife
{
    //這個方法相當(dāng)于Receiver類型的Action方法
    public void Execute(string job)
    {
        Console.WriteLine(job);
    }
}

六、命令模式的實現(xiàn)要點:

1、Command模式的根本目的在于將“行為請求者”與“行為實現(xiàn)者”解耦,在面向?qū)ο笳Z言中,常見的實現(xiàn)手段是“將行為抽象為對象”。
2、實現(xiàn)Command接口的具體命令對象ConcreteCommand有時候根據(jù)需要可能會保存一些額外的狀態(tài)信息。
3、通過使用Composite組合模式,可以將多個命令封裝為一個“復(fù)合命令”MacroCommand。
4、Command模式與C#中的Delegate有些類似。但兩者定義行為接口的規(guī)范有所區(qū)別:Command以面向?qū)ο笾械?ldquo;接口-實現(xiàn)”來定義行為接口規(guī)范,更嚴(yán)格,更符合抽象原則;Delegate以函數(shù)簽名來定義行為接口規(guī)范,更靈活,但抽象能力比較弱。
5、使用命令模式會導(dǎo)致某些系統(tǒng)有過多的具體命令類。某些系統(tǒng)可能需要幾十個,幾百個甚至幾千個具體命令類,這會使命令模式在這樣的系統(tǒng)里變得不實際。

1、命令模式的優(yōu)點:

(1)、命令模式使得新的命令很容易被加入到系統(tǒng)里。

(2)、可以設(shè)計一個命令隊列來實現(xiàn)對請求的Undo和Redo操作。
(3)、可以較容易地將命令寫入日志。
(4)、可以把命令對象聚合在一起,合成為合成命令。合成命令式合成模式的應(yīng)用。

2、命令模式的缺點:

使用命令模式可能會導(dǎo)致系統(tǒng)有過多的具體命令類。這會使得命令模式在這樣的系統(tǒng)里變得不實際。

3、命令模式的使用場景:

(1)、系統(tǒng)需要支持命令的撤銷(undo)。命令對象可以把狀態(tài)存儲起來,等到客戶端需要撤銷命令所產(chǎn)生的效果時,可以調(diào)用undo方法把命令所產(chǎn)生的效果撤銷掉。命令對象還可以提供redo方法,以供客戶端在需要時,再重新實現(xiàn)命令效果。
(2)、系統(tǒng)需要在不同的時間指定請求、將請求排隊。一個命令對象和原先的請求發(fā)出者可以有不同的生命周期。意思為:原來請求的發(fā)出者可能已經(jīng)不存在了,而命令對象本身可能仍是活動的。這時命令的接受者可以在本地,也可以在網(wǎng)絡(luò)的另一個地址。命令對象可以串行地傳送到接受者上去。
(3)、如果一個系統(tǒng)要將系統(tǒng)中所有的數(shù)據(jù)消息更新到日志里,以便在系統(tǒng)崩潰時,可以根據(jù)日志里讀回所有數(shù)據(jù)的更新命令,重新調(diào)用方法來一條一條地執(zhí)行這些命令,從而恢復(fù)系統(tǒng)在崩潰前所做的數(shù)據(jù)更新。
(4)、系統(tǒng)需要使用命令模式作為“CallBack(回調(diào))”在面向?qū)ο笙到y(tǒng)中的替代。Callback即是先將一個方法注冊上,然后再以后調(diào)用該方法。

七、.NET 中命令模式的實現(xiàn)

由于.NET有了Delegate,它很少很少用到Command。它只要需要用到行為抽象,它都用Delegate去做。因為這是Framework,這是和業(yè)務(wù)領(lǐng)域相關(guān)度不大的基礎(chǔ)建設(shè)層面,它是不太需要用到OO的層面。對于我們來說,我們建議更多地用Command去實現(xiàn)。

到此這篇關(guān)于.Net行為型設(shè)計模式之命令模式(Command)的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論