1.定义
命令模式(Command Pattern)又叫动作模式或事务模式。指的是将一个请求封装成一个对象,使发出请求的责任和执行请求的责任分割开,然后可以使用不同的请求把客户端参数化,这样可以使得两者之间通过命令对象进行沟通,从而方便将命令对象进行储存、传递、调用、增加与管理。命令模式是一种对象行为型模式。
命令模式就是对命令的封装,就是把一系列的操作写到一个方法中,然后供客户端调用就行了。主要的作用就是对请求发送者与接收者进行耦合,发送者与接收者之间没有直接引用关系,使得对象之间的调用关系更加灵活,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。
2.组成结构
命令模式主要由以下几个部分组成:
- 抽象命令类(Command):命令的抽象类,类中对需要执行的命令进行声明,一般来说要对外公布一个execute方法用来执行命令。
- 具体命令类(Concrete Command):抽象命令类的具体实现子类,对抽象类中声明的方法进行实现。
- 调用类(Invoker):调用者,负责调用命令,执行命令功能的相关操作,是具体命令对象业务的真正实现者。
- 接受类(Receiver):接收者,负责接收命令并且执行命令,是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
敲黑板:命令模式的核心是将一个请求封装成一个对象,注意是将请求封装成对象,而不是请求者或者是调用者。
3.示例代码
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
// 接受者,作为最底层的调用
class Receiver
{
public:
void BakeMutton()
{
cout << "烤羊肉" << endl;
}
void BakeChicken()
{
cout << "烤鸡翅" << endl;
}
};
// 基类
class Command
{
public:
Command(Receiver* pstReceiver) :m_pstReceiver(pstReceiver)
{
}
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 (auto it = m_vecPstCommand.begin(); it != m_vecPstCommand.end(); ++it)
{
(*it)->Excute();
}
}
private:
vector<Command*> m_vecPstCommand;
};
int main(int argc, char* argv[])
{
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 << "------------------" << endl << endl;
pstInvoke->Remove(pstConcreteCommandA); //撤销操作
pstInvoke->Remove(pstConcreteCommandB);
pstInvoke->Notify();
cout << "------------------" << endl << endl;
return 0;
}
/**
ConcreteCommandA excuting......
烤羊肉
ConcreteCommandA excuting......
烤羊肉
ConcreteCommandB excuting......
烤鸡翅
------------------
ConcreteCommandA excuting......
烤羊肉
------------------
**/
4.引用
从零开始学设计模式(二十二):命令模式(Command Pattern) - 知乎 (zhihu.com)