我所理解的設計模式(C++實現)——命令模式(Command Pattern)

來源:互聯網
上載者:User
概述:

        我們去餐廳吃飯,我們是通過服務員來點菜,具體是誰來做這些菜和他們什麼時候完成的這些菜,其實我們都不知道。抽象之,“菜單要求者”我們和“菜單實現者”廚師,2者之間是松耦合的,我們對這些菜的其他一些請求比如“撤銷,重做”等,我們也不知道是誰在做。其實這就是本文要說的Command模式。

        將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支援可撤消的操作。[GOF 《設計模式》]

類圖與執行個體:

角色用途:

客戶(Client)角色:建立了一個具體命令(ConcreteCommand)對象並確定其接收者。

命令(Command)角色:聲明了一個給所有具體命令類的抽象介面。這是一個抽象角色。

具體命令(ConcreteCommand)角色:定義一個接受者和行為之間的弱耦合;實現Execute()方法,負責調用接收考的相應操作。Execute()方法通常叫做執行方法。

要求者(Invoker)角色:負責調用命令對象執行請求,相關的方法叫做行動方法。

接收者(Receiver)角色:負責具體實施和執行一個請求。任何一個類都可以成為接收者,實施和執行請求的方法叫做行動方法。

執行個體:

#include <iostream>#include <vector>using namespace std;// 烤肉師傅class RoastCook{public:void MakeMutton() { cout << "烤羊肉" << endl; }void MakeChickenWing() { cout << "烤雞翅膀" << endl; }};// 抽象命令類class Command{public:Command(RoastCook* temp) { receiver = temp; }virtual void ExecuteCmd() = 0;protected:RoastCook* receiver;};// 烤羊肉命令class MakeMuttonCmd : public Command{public:MakeMuttonCmd(RoastCook* temp) : Command(temp) {}virtual void ExecuteCmd() { receiver->MakeMutton(); }};// 烤雞翅膀命令class MakeChickenWingCmd : public Command{public:MakeChickenWingCmd(RoastCook* temp) : Command(temp) {}virtual void ExecuteCmd() { receiver->MakeChickenWing(); }};// 服務員類class Waiter{public:void SetCmd(Command* temp);// 通知執行void Notify();protected:vector<Command*> m_commandList;};void Waiter::SetCmd(Command* temp){m_commandList.push_back(temp);cout << "增加訂單" << endl;}void Waiter::Notify(){vector<Command*>::iterator it;for (it=m_commandList.begin(); it!=m_commandList.end(); ++it){(*it)->ExecuteCmd();}}int main(){// 店裡添加烤肉師傅、菜單、服務員等顧客RoastCook* cook = new RoastCook();Command* cmd1 = new MakeMuttonCmd(cook);Command* cmd2 = new MakeChickenWingCmd(cook);Waiter* girl = new Waiter();// 點菜girl->SetCmd(cmd1);girl->SetCmd(cmd2);// 服務員通知girl->Notify();return 0;}

效果與實現要點:

1.Command模式的根本目的在於將“行為要求者”與“行為實現者”解耦,在物件導向語言中,常見的實現手段是“將行為抽象為對象”。

2.實現Command介面的具體命令對象ConcreteCommand有時候根據需要可能會儲存一些額外的狀態資訊。

3.通過使用Compmosite模式,可以將多個命令封裝為一個“複合命令”MacroCommand。

4.Command模式與C#中的Delegate有些類似。但兩者定義行為介面的規範有所區別:Command以物件導向中的“介面-實現”來定義行為介面規範,更嚴格,更符合抽象原則;Delegate以函數簽名來定義行為介面規範,更靈活,但抽象能力比較弱。

5.使用命令模式會導致某些系統有過多的具體命令類。某些系統可能需要幾十個,幾百個甚至幾千個具體命令類,這會使命令模式在這樣的系統裡變得不實際。

適用性:

在下面的情況下應當考慮使用命令模式:

1.使用命令模式作為"CallBack"在物件導向系統中的替代。"CallBack"講的便是先將一個函數登記上,然後在以後調用此函數。

2.需要在不同的時間指定請求、將請求排隊。一個命令對象和原先的請求發出者可以有不同的生命期。換言之,原先的請求發出者可能已經不在了,而命令對象本身仍然是活動的。這時命令的接收者可以是在本地,也可以在網路的另外一個地址。命令對象可以在串形化之後傳送到另外一台機器上去。

3.系統需要支援命令的撤消(undo)。命令對象可以把狀態儲存起來,等到用戶端需要撤銷命令所產生的效果時,可以調用undo()方法,把命令所產生的效果撤銷掉。命令對象還可以提供redo()方法,以供用戶端在需要時,再重新實施命令效果。

4.如果一個系統要將系統中所有的資料更新到日誌裡,以便在系統崩潰時,可以根據日誌裡讀回所有的資料更新命令,重新調用Execute()方法一條一條執行這些命令,從而恢複系統在崩潰前所做的資料更新。


LCL_data原創於CSDN.NET【http://blog.csdn.net/lcl_data/article/details/9080909】

其他設計模式文章請查看我所理解的設計模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.