設計模式之命令模式


命令模式介紹

命令

命令模式最初的感受是把邏輯實現與操作請求進行分離,降低耦合方便擴展。

命令模式是一種行為模式,以數據驅動的方式將命令對象,通過構造函數的形式傳遞給調用者。調用者再提供相應的實現為命令執行提供操作方法。

命令場景的核心的邏輯是調用方不需要去關心具體的邏輯實現,它只管調用它需要的模塊,而被調用方也不需要關心被誰調用,它只負責完成模塊的實現就行。

命令模式的使用場景需要分為三個比較大的塊:命令、實現、調用者,而這三塊內容的拆分也是選擇適合場景的關鍵因素,經過這樣的拆分可以讓邏輯具備單一職責的性質,便於擴展。

命令模式可將請求轉換為一個包含與請求相關的所有信息的獨立對象。該轉換讓你能根據不同的請求將方法參數化、延遲請求執行或將其放入隊列中且能實現可撤銷操作。

優秀的軟件設計通常會將關注點進行分離,而這往往會導致軟件的分層。

命令模式的結構

  • 發送者

    也可叫觸發者,負責對請求進行初始化,其中必須包含一個成員變量來存儲對於命令對象的引用。發送者觸發命令,而不向接收者直接發送請求。

  • 命令

    通常僅聲明一個執行命令的方法

  • 具體命令

    實現各種類型的請求。具體命令自身並不完成工作,而是會將委派給一個業務邏輯對象。

  • 接收者

    包含部分業務邏輯,幾乎任何對象都可以作為接收者。絕大部分命令只處理如何將請求傳遞到接收者的細節,接收者自己會完成實際的工作。

  • 客戶端

    創建並配置具體命令對象。客戶端必須將包括接收者實體在內的所有請求傳遞給命令的構造函數。

適用場景

  • 通過操作來參數化對象
  • 想將操作放入隊列中、操作的執行或者遠程執行操作
  • 實現操作回滾功能

命令模式的實現方式

1、聲明僅有一個執行方法的命令接口。

2、抽取請求並使之成為實現命令接口的具體命令類。每個類都必須有一組成員變量來保存請求參數和對於實際接收者對象的引用。

3、找到擔任發送者職責的類,在這些類中添加保存命令的成員變量。發送者只能通過命令接口與其命令進行交互。發送者自身通常並不創建命令對象,而是通過客戶端代碼獲取。

4、修改發送者使其執行命令,而非直接將請求發送給接收者。

5、客戶端必須按照以下順序來初始化對象。

  • 創建接收者
  • 創建命令
  • 創建發送者並將其與特定命令關聯

Demo

命令模式可以通過抽象或接口類型(發送者)中的行為方法來識別,該類型調用另一個不同的抽象或接口類型(接收者)實現中的方法,該實現則是在創建時由命令模式的實現封裝。

接口與實現類

    /// <summary>
    /// 簡單命令    實現命令接口
    /// </summary>
    class SimpleCommand : ICommand
    {
        private string _info;

        public SimpleCommand(string message)
        {
            this._info = message;
        }
        public void Execute()
        {
            Console.WriteLine("執行簡單命令,"+_info);
        }        
    }

    /// <summary>
    /// 復雜命令    實現命令接口
    /// </summary>
    class ComplexCommand : ICommand
    {
        Receiver _receiver;
        private string _complexOneInfo;

        private string _complexTwoInfo;

        public ComplexCommand(Receiver receiver,string oneInfo,string twoInfo)
        {
            _receiver = receiver;
            _complexOneInfo = oneInfo;
            _complexTwoInfo = twoInfo;
        }

        public void Execute()
        {
            Console.WriteLine("執行復雜命令");
            _receiver.DoOne(_complexOneInfo);
            _receiver.DoTwo(_complexTwoInfo);
        }
    }

接收者

    /// <summary>
    /// 接收者
    /// </summary>
    class Receiver 
    {
        public void DoOne(string oneInfo) 
        {
            Console.WriteLine("接收的信息為:"+oneInfo);
        }

        public void DoTwo(string oneInfo) 
        {
            Console.WriteLine("接收的信息為:" + oneInfo);
        }
    }

調用者

    /// <summary>
    /// 調用者Invoker 
    /// </summary>
    public class InvokerClient
    {
        private ICommand _one;
        private ICommand _two;

        public void SetOnOne(ICommand com) 
        {
            _one = com;
        }

        public void SetOnTwo(ICommand com) 
        {
            _two = com;
        }

        public void DoExecute() 
        {
            Console.WriteLine("調用者One的打印");
            if (_one is ICommand)
            {
                _one.Execute();
            }

            Console.WriteLine("調用者Two的打印");
            if (_two is ICommand)
            {
                _two.Execute();
            }                 
        }
    }

實現結果

此模式在執行一些業務邏輯比較條理化的需求時,可以被使用。通過將業務中的鏈條關系,整合成一個個命令,調用者直接調用對應的命令接口就行,根本不需要知道是誰,如何提供的方法。而且實現方法的人也不知道誰調用的,如何調用的,這些對於它們來說都是不相關的,也滿足單一職責和開閉原則。

小寄語

原創不易,給個關注唄。

人生短暫,我不想去追求自己看不見的,我只想抓住我能看的見的。

我是阿輝,感謝您的閱讀,如果對你有幫助,麻煩關注、點贊、轉發 謝謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM