設計模式學習總結-命令模式(Cmmand Pattern)


問題:
在面向對象的軟件設計中,經常會遇到一個(或一系列)對象,對象本身的數據存儲與對象的操作耦合在一起。例如一個對象有add(),edit(),delete()方法,這樣對象支持的方法很難擴展,如果需要加入update()就必須修改代碼,客戶端與對象也是緊耦合的。命令模式是將一類對象的功能(行為,功能)抽象成一個命令對象,客戶端在使用的時候,只與該命令對象打交道,而不用與對象打交道,分離命令的請求者和命令的執行者,降低了耦合性,可以使用不同的請求對客戶進行參數化提高了程序設計的靈活性。

定義:
命令模式(Command)模式,將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支持可撤消的操作。
意圖:

提供一個抽象的Command接口,將執行命令操作的方法封裝到Command類接口中,ConcreteCommand實現這個Command接口方法,通過調用Receiver實例變量處理請求。客戶端定義一個Invoker對象存儲該concreteCommand對象,該invoker通過調用command對象的遞交一個請求。

參與者:
•抽象命令角色(Command):  
定義命令的接口,聲明執行的方法。   
具體命令角色(ConcreteCommand):   
命令接口實現對象,是“虛”的實現;通常會持有接收者,並調用接收者的功能來完成命令要執行的操作。  
•請求者(Invoker):
要求命令對象執行請求,通常會持有命令對象,可以持有很多的命令對象。這個是客戶端真正觸發命令並要求命令執行相應操作的地方,也就是說相當於使用命令對象的入口。  
•接收者(Receiver、執行者):   
接收者,真正執行命令的對象。任何類都可能成為一個接收者,只要它能夠實現命令要求實現的相應功能。
•客戶端(Client):   
創建具體的命令對象,並且設置命令對象的接收者。注意這個不是我們常規意義上的客戶端,而是在組裝命令對象和接收者,或許,把這個Client稱為裝配者會更好理解,因為真正使用命令的客戶端是從Invoker來觸發執行。

UML圖:

 

實例說明:

諾基亞手機工廠
公司(Client)通知生產部(Invoker),生產兩部n8,兩部n9,生產部通過“命令模式”,將生產任務交給手機工廠(Receiver),生產手機。

uml圖如下:

  

代碼:

///   <summary>
///  手機生產命令接口(Command)
///   </summary>
public  interface ICreatePhoneCommand
{
     void Execute();
}
///   <summary>
///  N8手機生產具體命令類(ConcreteCommand)
///   </summary>
public  class CreateNokiaN8Command : ICreatePhoneCommand
{
    PhoneFactory phoneFactory =  null;

     public CreateNokiaN8Command(PhoneFactory _phoneFactory)
    {
        phoneFactory = _phoneFactory;
    }
     public  void Execute()
    {
            phoneFactory.CreateNokiaN8();
    }
}
///   <summary>
///  N8手機生產具體命令類(ConcreteCommand)
///   </summary>
public  class CreateNokiaN9Command : ICreatePhoneCommand
{
    PhoneFactory phoneFactory =  null;
     public CreateNokiaN9Command(PhoneFactory _phoneFactory)
    {
        phoneFactory = _phoneFactory;
    }
     public  void Execute()
    {
        phoneFactory.CreateNokiaN9();
    }
}
///   <summary>
///  手機生產工廠(Receiver)具體的手機生產
///   </summary>
public  class PhoneFactory 
{
     public  void CreateNokiaN8()
    {
        System.Console.WriteLine( " 一部Nokia N8 生產完成 ");
    }
     public  void CreateNokiaN9()
    {
        System.Console.WriteLine( " 一部Nokia N9 生產完成 ");
    }
}
///   <summary>
///  生產部對象(Invoker)接收生產信息,制定生產清單。通知PhoneFactory生產
///   </summary>
public  class LiaisonCreate
{
    List<ICreatePhoneCommand> createPhoneCommandList =  new List<ICreatePhoneCommand>();
     ///   <summary>
    
///  添加生產任務
    
///   </summary>
    
///   <param name="_createPhoneCommand"></param>
     public  void AddCreatePhoneTask(ICreatePhoneCommand _createPhoneCommand)
    {
        createPhoneCommandList.Add(_createPhoneCommand);
    }
     ///   <summary>
    
///  撤銷生產任務
    
///   </summary>
    
///   <param name="_createPhoneCommand"></param>
     public  void CancelCreatePhoneTask(ICreatePhoneCommand _createPhoneCommand)
    {
        createPhoneCommandList.Remove(_createPhoneCommand);
    }
     ///   <summary>
    
///  執行生產
    
///   </summary>
     public  void CreatePhone()
    {
         foreach ( var createPhoneCommand  in createPhoneCommandList)
        {
            createPhoneCommand.Execute();
        }
    }
}
public   void CommandTest()
{
     // 初始化生產部聯系人
    LiaisonCreate liaisonCreate =  new LiaisonCreate();
     // 初始化生產工廠
    PhoneFactory phoneFactory =  new PhoneFactory();
     // 設置生產清單
    liaisonCreate.AddCreatePhoneTask( new CreateNokiaN8Command(phoneFactory));
    liaisonCreate.AddCreatePhoneTask( new CreateNokiaN8Command(phoneFactory));
    liaisonCreate.AddCreatePhoneTask( new CreateNokiaN9Command(phoneFactory));
    liaisonCreate.AddCreatePhoneTask( new CreateNokiaN9Command(phoneFactory));
     // 取消一部N9的生產
    liaisonCreate.CancelCreatePhoneTask( new CreateNokiaN9Command(phoneFactory));

     // 開始執行生產
    liaisonCreate.CreatePhone();
    System.Console.Read();
}

 

優點:
•命令模式將發出命令的責任和執行命令的責任分割開,降低系統的耦合度。 
•新的命令可以很容易地加入到系統中。只要實現了抽象命令接口的具體命令類就可以與接收者相關聯。  
•可以比較容易地設計一個組合命令,形成一個輕量級的事件隊列
•命令模式使請求本身成為一個對象,這個對象和其他對象一樣可以被存儲和傳遞。
•請求方不必知道接收請求的接口,執行命令的細節(只需客戶端為concreteCommand對象指定一個receiver對象即可)起到了很好的封裝隔離作用. 

缺點:

•每一個命令都需要設計一個具體命令類,使用命令模式會導致某些系統有過多的具體命令類。
 

應用情景:
•系統需要將請求調用者和請求接收者解耦,使得調用者和接收者不直接交互。   
•系統需要在不同的時間指定請求、將請求排隊和執行請求。   
•系統需要支持命令的撤銷(Undo)操作和恢復(Redo)操作。   
•系統需要將一組操作組合在一起,即支持宏命令。


免責聲明!

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



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