行爲型模式
行爲型模式 | 類型 |
---|---|
關注對象之間的通信 | 命令模式(Command Pattern) 責任鏈模式(Chain of Responsibility Pattern ) 解釋器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 備忘錄模式(Memento Pattern) 觀察者模式(Observer Pattern) 狀態模式(State Pattern) 空對象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 訪問者模式(Visitor Pattern) |
命令模式
命令模式(Command Pattern)是一種數據驅動的設計模式,它屬於行爲型模式。請求以命令的形式包裹在對象中,並傳給調用對象。調用對象尋找可以處理該命令的合適的對象,並把該命令傳給相應的對象,該對象執行命令。
意圖:將一個請求封裝成一個對象,從而使您可以用不同的請求對客戶進行參數化。 在OOP中,一切都是對象,將請求封裝成對象,符合OOP的設計思想,當將客戶的單個請求封裝成對象以後,我們就可以對這個請求存儲更多的信息,使請求擁有更多的能力;命令模式同樣能夠把請求發送者和接收者解耦,使得命令發送者不用去關心請求將以何種方式被處理。
參與者
- Command:聲明執行操作的接口;
- ConcreteCommand:將一個接收者對象綁定於一個動作,之後,調用接收者相應的操作,以實現Execute來完成相應的命令;
- Client:創建一個具體命令對象,但是並沒有設定它的接收者; Invoker:要求該命令執行這個請求;
- Receiver:知道如何實施與執行一個請求相關的操作,任何類都可能作爲一個接收者。
協作
- Client創建一個ConcreteCommand命令對象,並指定它的Receiver對象
- Invoker對象存儲該ConcreteCommand對象;
- 該Invoker通過調用Command對象的Execute操作來提交一個請求。如果這個命令請求是可以撤銷的,ConcreteCommand就執行Execute操作之前存儲當前狀態以用於取消該命令請求;
- ConcreteCommand對象調用Receiver的一些操作以執行該請求。
優點:
- 降低了系統耦合度。
- 新的命令可以很容易添加到系統中去。
缺點:
- 使用命令模式可能會導致某些系統有過多的具體命令類。
具體事例:
我們去餐廳吃飯,我們是通過服務員來點菜,具體是誰來做這些菜和他們什麼時候完成的這些菜,其實我們都不知道。抽象之,我們是“菜單請求者”,廚師是“菜單實現者”,2者之間是鬆耦合的,我們對這些菜的其他一些請求比如“撤銷,重做”等,我們也不知道是誰在做。其實這就是本文要說的Command模式。將一個請求封裝爲一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可撤消的操作。[GOF 《設計模式》]
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#define SAFE_DELETE(p) if (p) { delete p; p = NULL; }
/*烤肉師傅類,只負責烤串工作*/
class Barbecuer
{
public:
void BakeMutton(){cout<<"Bake mutton"<<endl;}
void BakeChickenWing(){cout<<"Bake ChickenWing"<<endl;}
};
/*抽象命令類:是執行具體操作的接口*/
class Command
{
public:
Command(){}
Command(Barbecuer *receiver):p_receiver(receiver){}
virtual void ExecuteCommand() = 0; //執行命令
protected:
Barbecuer *p_receiver;
};
/*具體命令類:烤羊肉串命令*/
class BakeMuttonCommand:public Command
{
public:
BakeMuttonCommand(Barbecuer *receiver){p_receiver = receiver;}
void ExecuteCommand(){p_receiver->BakeMutton();}
};
/*具體命令類:烤雞翅串命令*/
class BakeChickenWingCommand:public Command
{
public:
BakeChickenWingCommand(Barbecuer *receiver){p_receiver = receiver;}
void ExecuteCommand()
{p_receiver->BakeChickenWing();}
};
/*服務員類*/
class Waiter
{
public:
void SetOrder(Command *command);
void Notify();
private:
vector<Command *>p_commandList; //這裏相當於一個命令對象隊列
};
void Waiter::SetOrder(Command *command)
{
p_commandList.push_back(command);
cout << "增加烤肉命令" << endl;
}
void Waiter::Notify()
{
vector<Command*>::iterator i;
for(i = p_commandList.begin(); i != p_commandList.end(); ++ i)
(*i)->ExecuteCommand();
}
int main(int argc, char *argv[])
{
//生成烤肉師傅、服務員、訂單對象
Barbecuer *p_cook = new Barbecuer();
Command *p_mutton = new BakeMuttonCommand(p_cook);
Command *p_chickenwing = new BakeChickenWingCommand(p_cook);
Waiter *p_waiter = new Waiter();
//將訂單對象推送到命令隊列
p_waiter->SetOrder(p_mutton);
p_waiter->SetOrder(p_chickenwing);
//服務員通知烤肉師傅具體訂單
p_waiter->Notify();
SAFE_DELETE(p_cook);
SAFE_DELETE(p_mutton);
SAFE_DELETE(p_chickenwing);
SAFE_DELETE(p_waiter);
return 0;
}
參考:
https://www.cnblogs.com/lizhanwu/p/4435359.html
https://www.runoob.com/design-pattern/command-pattern.html