命令模式
模式定义
- 命令模式是一种行为定义模式,可以将请求转换成一个与请求相关的,包含该请求所有信息的独立对象,并且能够根据不同请求将方法参数化,延迟请求执行或者将其放入到队列中且能实现撤销等操作
模式动机
- 敏捷开发的原则要求,不要在代码上添加基于猜测的,实际上不需要的功能。如果不清楚一个系统是否需要命令模式,一般不要急着去实现它,事实上,在需要的时候通过重构实现这个模式并不难,只有在真正需要撤销/恢复操作功能的时候,将原有的代码重构为命令才合适
UML 类图
代码实例
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
using namespace std;
class Receiver
{
public:
void BakeMutton(){
cout << "Bake mutton..." << endl;
}
void BakeChicken(){
cout << "Bake chicken..." << endl;
}
};
class Command
{
public:
Command(Receiver* pstRecevier):m_pstReceiver(pstRecevier){}
virtual void Excute() = 0;
protected:
Receiver* m_pstReceiver;
};
class ConcreteCommandA : public Command
{
public:
ConcreteCommandA(Receiver* pstReceiver):Command(pstReceiver){
}
virtual void Excute(){
cout << "ConcreteCommandA excuting..." << endl;
m_pstReceiver->BakeMutton();
}
};
class ConcreteCommandB : public Command
{
public:
ConcreteCommandB(Receiver* pstReceiver):Command(pstReceiver){
}
virtual void Excute(){
cout << "ConcreteCommandB excuting..." << endl;
m_pstReceiver->BakeChicken();
}
};
class Invoke{
public:
void Add(Command* pstCommand){
m_vecPstCommand.push_back(pstCommand);
}
void Remove(Command* pstCommand){
m_vecPstCommand.erase(find(m_vecPstCommand.begin(), m_vecPstCommand.end(),pstCommand));
}
void RemoveAll(){
m_vecPstCommand.clear();
}
void Notify(){
for(typeof(m_vecPstCommand.begin()) it = m_vecPstCommand.begin(); it != m_vecPstCommand.end(); it++){
(*it)->Excute();
}
}
private:
vector<Command*> m_vecPstCommand;
};
int main()
{
Receiver* pstReceiver = new Receiver;
Command* pstConcreteCommandA = new ConcreteCommandA(pstReceiver);
Command* pstConcreteCommandB = new ConcreteCommandB(pstReceiver);
Invoke* pstInvoke = new Invoke();
pstInvoke->Add(pstConcreteCommandA);
pstInvoke->Add(pstConcreteCommandA);
pstInvoke->Add(pstConcreteCommandB);
pstInvoke->Notify();
cout << "-----------First Call End---------" << endl;
pstInvoke->Remove(pstConcreteCommandA);
pstInvoke->Remove(pstConcreteCommandB);
pstInvoke->Notify();
cout << "-----------Second Call End---------" << endl;
}
优缺点
优点:
- 类间解耦,调用者和接收者没有没有直接耦合,调用这只需要调用 Command 的方法执行接收者的业务逻辑即可
- 可扩展性,如果 Command 需要扩展,只需要新增一个子类即可
缺点
- 如果命令很多,则意味着 Command 子类很多,增加了系统的复杂性