C++命令模式(Command)

    xiaoxiao2023-11-20  177

    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、新的命令可以很容易添加到系统中去

    最新回复(0)