1. 命令模式介绍
1.1 定义
命令模式的英文翻译是 Command Design Pattern。在 GoF 的《设计模式》一书中,它是这么定义的:
The command pattern encapsulates a request as an object, thereby letting us parameterize other objects with different requests, queue or log requests, and support undoable operations.
- 中文翻译为:
命令模式:将请求封装成对象,以便使用不同的请求、日志、队列等来参数化其他对象。命令模式也支持撤销操作。
- 命令模式的本质:封装请求
- 设计意图:命令模式通过将请求封装到一个命令(Command)对象中,实现了请求调用者和具体实现者之间的解耦。
1.2 应用场景
在需要事务的系统中,可以选用命令模式。命令模式提供了对事务进行建模的方法。命令模式有一个别名就是Transaction。
命令模式,类似于C语言里的回调函数。
1.3 命令模式的结构
命令模式涉及的角色及其职责如下:
- 抽象命令(Command):一般定义为接口,用来定义执行命令的接口。
- 具体命令(ConcreteCommand)角色:通常会持有接收者对象,并调用接收者对象的相应功能来完成命令要执行的操作。
- 接收者(Receiver)角色:真正执行命令的对象。任何类都可能成为接收者,只要它能够实现命令要求实现的相应功能。
- 调用者(Invoker)角色:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
- 客户端(Client)角色:创建具体的命令对象,并且设置命令对象的接收者。
2. 示例代码
以客人点餐为例,实现:点餐和cook隔离。
// CommandModel.h文件#pragma once#include <iostream>#include <vector>#include <algorithm>// 烤肉师傅class BarbecueMaster{public: void MakeMutton() { std::cout << "烤羊腿喽" << std::endl; } void MakeChiken() { std::cout << "烤鸡肉喽" << std::endl; }};// 命令类class Command{protected: BarbecueMaster * m_master;public: Command(BarbecueMaster * p) { m_master = p; } virtual void executeCmd() = 0;};// 命令1class CommandMutton : public Command{public: CommandMutton(BarbecueMaster * p) : Command(p) {} void executeCmd() { m_master->MakeMutton(); }};// 命令2class CommandChiken : public Command{public: CommandChiken(BarbecueMaster * p) : Command(p) {} void executeCmd() { m_master->MakeChiken(); }};// 服务员class Waiter{private: std::vector<Command *> m_vec;public: ~Waiter() { for (auto it = m_vec.begin(); it != m_vec.end(); it++) { delete(*it); } m_vec.clear(); } // Waiter Func1 void add(Command * p) { m_vec.push_back(p); } // Waiter Func2 void remove(Command * p) { auto it = find(m_vec.begin(), m_vec.end(), p); if (it != m_vec.end()) m_vec.erase(it); } // Waiter Func3 void submitCmd() { for (auto it = m_vec.cbegin(); it != m_vec.cend(); it++) { (*it)->executeCmd(); } }};
测试代码:
#include <iostream>#include "CommandModel.h"int main(){ using namespace std; // 命令模式 Waiter * pWaiter = new Waiter(); BarbecueMaster * pMaster = new BarbecueMaster(); pWaiter->add(new CommandChiken(pMaster)); pWaiter->add(new CommandMutton(pMaster)); pWaiter->submitCmd(); delete pMaster; delete pWaiter; getchar(); return 0;}