UML类图(仅供参考)如下:
命令模式解决的问题:
在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令
源码
#include <iostream>
#include <string>
#include <list>
// 烧烤厨师
class CBarbecuer
{
public:
// 厨师的一个功能为烤羊肉串
void BakeMutton()
{
std::cout << "烧烤厨师:我正在烤一串羊肉串:" << std::endl;
}
// 厨师的一个功能为烤鸡翅
void BakeChickenWing()
{
std::cout << "烧烤厨师:我正在烤一个鸡翅:" << std::endl;
}
};
// 抽象命令类,控制厨师到底烤什么肉
class CCommand
{
public:
// 确定执行烤肉的厨师
CCommand(CBarbecuer *pcBarbecuer) :m_pcBarbecuer(pcBarbecuer) {}
virtual ~CCommand() {}
virtual void ExcuteCommand() = 0;
std::string& GetCmdStr()
{
return m_sCmd;
}
protected:
CBarbecuer *m_pcBarbecuer;
// 命令描述,确定厨师到底烤什么肉
std::string m_sCmd;
};
// 烤羊肉串命令类
class CBakeMutton :public CCommand
{
public:
CBakeMutton(CBarbecuer *pcBarbecuer) :CCommand(pcBarbecuer)
{
// 给厨师设置命令为考羊肉串
m_sCmd = "BakeMutton";
}
void ExcuteCommand()
{
m_pcBarbecuer->BakeMutton();
}
};
// 烤鸡翅命令类
class CBakeChickenWing :public CCommand
{
public:
CBakeChickenWing(CBarbecuer *pcBarbecuer) :CCommand(pcBarbecuer)
{
// 给厨师设置命令为考鸡翅
m_sCmd = "BakeChickenWing";
}
void ExcuteCommand()
{
m_pcBarbecuer->BakeChickenWing();
}
};
// 服务员类
class CWaiter
{
public:
CWaiter() :m_listCmd(new std::list<CCommand*>()) {}
// 添加一个命令
void SetOrder(CCommand *pcCommand)
{
if ("BakeMutton" == pcCommand->GetCmdStr())
{
if (m_iAlreadyMuttoCount >= m_iMuttoCount)
{
std::cout << "服务员:羊肉串已经没有了" << std::endl;
}
else
{
// 修改类成员,本来是要加锁的,这里暂时不处理
++m_iAlreadyMuttoCount;
std::cout << "服务员:增加一串烤羊肉串" << std::endl;
m_listCmd->push_back(pcCommand);
}
}
else if("BakeChickenWing" == pcCommand->GetCmdStr())
{
if (m_iAlreadyChickenWing >= m_iChickenWing)
{
std::cout << "服务员:鸡翅已经没有了" << std::endl;
}
else
{
// 修改类成员,本来是要加锁的,这里暂时不处理
++m_iAlreadyChickenWing;
std::cout << "服务员:增加一个鸡翅" << std::endl;
m_listCmd->push_back(pcCommand);
}
}
else
{
}
}
void CancelOrder(CCommand *pcCommand)
{
auto it = std::find(m_listCmd->begin(), m_listCmd->end(), pcCommand);
if (it != m_listCmd->end())
{
if ("BakeMutton" == pcCommand->GetCmdStr())
{
// 修改类成员,本来是要加锁的,这里暂时不处理
--m_iAlreadyMuttoCount;
std::cout << "服务员:取消一串羊肉串" << std::endl;
}
else if ("BakeChickenWing" == pcCommand->GetCmdStr())
{
// 修改类成员,本来是要加锁的,这里暂时不处理
--m_iAlreadyChickenWing;
std::cout << "服务员:取消一个鸡翅" << std::endl;
}
else
{
}
m_listCmd->erase(it);
}
}
void Notify()
{
for (CCommand* var : *m_listCmd)
{
var->ExcuteCommand();
}
}
private:
// 记录客人要点的才(命令链表)
std::list<CCommand*> *m_listCmd;
// 羊肉串总个数
const int m_iMuttoCount = 3;
// 鸡翅总个数
const int m_iChickenWing = 4;
// 当前所有的客人已经点了多少羊肉串
static int m_iAlreadyMuttoCount;
// 当前所有的客人已经点了多少鸡翅
static int m_iAlreadyChickenWing;
};
int CWaiter::m_iAlreadyMuttoCount = 0;
int CWaiter::m_iAlreadyChickenWing = 0;
int main()
{
// 烧烤店开张前得有一个厨师
CBarbecuer *pBarbecuer = new CBarbecuer();
// 烧烤店开张前得有一个服务员
CWaiter *pWaiter = new CWaiter();
// 客人选择烧烤(创建命令)
CCommand *bakeMutton1 = new CBakeMutton(pBarbecuer);
CCommand *bakeMutton2 = new CBakeMutton(pBarbecuer);
CCommand *bakeMutton3 = new CBakeMutton(pBarbecuer);
CCommand *bakeMutton4 = new CBakeMutton(pBarbecuer);
CCommand *bakeChickenWing1 = new CBakeChickenWing(pBarbecuer);
CCommand *bakeChickenWing2 = new CBakeChickenWing(pBarbecuer);
CCommand *bakeChickenWing3 = new CBakeChickenWing(pBarbecuer);
CCommand *bakeChickenWing4 = new CBakeChickenWing(pBarbecuer);
CCommand *bakeChickenWing5 = new CBakeChickenWing(pBarbecuer);
CCommand *bakeChickenWing6 = new CBakeChickenWing(pBarbecuer);
// 客人向服务员点烧烤(添加命令)
pWaiter->SetOrder(bakeMutton1);
pWaiter->SetOrder(bakeMutton2);
pWaiter->SetOrder(bakeMutton3);
pWaiter->SetOrder(bakeMutton4);
pWaiter->SetOrder(bakeChickenWing1);
pWaiter->SetOrder(bakeChickenWing2);
pWaiter->SetOrder(bakeChickenWing3);
pWaiter->SetOrder(bakeChickenWing4);
pWaiter->SetOrder(bakeChickenWing5);
pWaiter->SetOrder(bakeChickenWing6);
// 客人向服务员取消烧烤(取消命令)
pWaiter->CancelOrder(bakeMutton3);
pWaiter->CancelOrder(bakeChickenWing6);
// 服务员通知烧烤厨师按照菜单开始烤烧烤
pWaiter->Notify();
}
好处
1、降低了系统耦合度。
2、新的命令可以很容易添加到系统中去