命令模式
#include <iostream>
#include <list>
#ifdef _DEBUG //只在Debug(调试)模式下
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) //重新定义new运算符
#define new DEBUG_NEW
#endif
#endif
//#include <boost/type_index.hpp>
using namespace std;
//#pragma warning(disable : 4996)
namespace _nmsp1
{
//厨师类
class Cook
{
public:
//做红烧鱼
void cook_fish()
{
cout << "做一盘红烧鱼菜品" << endl;
}
//做锅包肉
void cook_meat()
{
cout << "做一盘锅包肉菜品" << endl;
}
//做其他各种菜品......略
};
//----------------------
//厨师做的每样菜品对应的抽象类
class Command
{
public:
Command(Cook* pcook)
{
m_pcook = pcook;
}
//做父类时析构函数为虚函数
virtual ~Command()
{
}
virtual void Execute() = 0;
//virtual void Undo() = 0;
protected:
Cook* m_pcook; //子类需要访问
};
//做红烧鱼菜品命令
// **cook中一个函数对应一个Command**
// 上层不直接操作接受者(Cook)
class CommandFish :public Command
{
public:
CommandFish(Cook* pcook) :Command(pcook) {}
virtual void Execute()
{
m_pcook->cook_fish();
}
};
//做锅包肉菜品命令
class CommandMeat :public Command
{
public:
CommandMeat(Cook* pcook) :Command(pcook) {}
virtual void Execute()
{
m_pcook->cook_meat(); //将一个动作封装成了一个对象
}
};
//-----------------
/*
//服务员类
class Waiter
{
public:
void SetCommand(Command* pcommand) //顾客把便签交给服务员
{
m_pcommand = pcommand;
}
void Notify() //服务器员将便签交到厨师手里让厨师开始做菜
{
m_pcommand->Execute();
}
private:
Command* m_pcommand; //服务员手中握着顾客书写的菜品便签
};*/
//服务员类
class Waiter
{
public:
//将顾客的便签增加到便签列表中,即便一个便签中包含多个菜品,这也相当于一道一道菜品加入到列表中
void AddCommand(Command* pcommand)
{
m_commlist.push_back(pcommand);
}
//如果顾客想撤单则将便签从列表中删除
void DelCommand(Command* pcommand)
{
m_commlist.remove(pcommand);
}
void Notify() //服务员将所有便签一次性交到厨师手里让厨师开始按顺序做菜
{
//依次让厨师做每一道菜品
for (auto iter = m_commlist.begin(); iter != m_commlist.end(); ++iter)
{
(*iter)->Execute();
}
}
private:
//一个便签中可以包含多个菜品甚至可以一次收集多个顾客的便签,达到一次性通知厨师做多道菜的效果
std::list<Command*> m_commlist; //菜品列表,每道菜品作为一项,如果一个便签中有多个菜品,则这里将包含多项
};
}
int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口
//第9章 命令(Command)模式:行为型模式。
//(1)通过一个范例引出命令模式代码编写方法
//红烧鱼,锅包肉
//(2)引入命令(Command)模式:五种角色
//a)Receiver(接收者类):Cook类,cook_fish,cook_meat;
//b)Invoker(调用者类):Waiter类。
//c)Command(抽象命令类):Command类。
//d)ConcreteCommand(具体命令类):CommandFish类和CommandMeat类。
//e)Client(客户端)
//定义:命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队
//或记录请求日志。以及支持可撤销的操作。
//说白了,就是将一系列的请求命令封装起来,不直接调用真正执行者的方法,这样比较好扩展。
//能力:对请求进行封装,命令对象将动作和接收者包裹到了对象中并只暴露了一个Execute方法让接收者执行动作。
//(3)命令模式用途研究:异步执行、延迟执行、排队执行、撤销、执行过程中增加日志记录等,是命令模式主要应用场景
/*
_nmsp1::Cook* pcook = new _nmsp1::Cook();
pcook->cook_fish();
pcook->cook_meat();
//释放资源
delete pcook;
*/
/*
_nmsp1::Cook cook;
_nmsp1::Command* pcmd1 = new _nmsp1::CommandFish(&cook);
pcmd1->Execute(); //做红烧鱼
_nmsp1::Command* pcmd2 = new _nmsp1::CommandMeat(&cook);
pcmd2->Execute(); //做锅包肉
//释放资源
delete pcmd1;
delete pcmd2;
*/
/*
_nmsp1::Cook cook;
_nmsp1::Waiter *pwaiter = new _nmsp1::Waiter();
_nmsp1::Command* pcmd1 = new _nmsp1::CommandFish(&cook);
pwaiter->SetCommand(pcmd1);
pwaiter->Notify(); //做红烧鱼
_nmsp1::Command* pcmd2 = new _nmsp1::CommandMeat(&cook);
pwaiter->SetCommand(pcmd2);
pwaiter->Notify(); //做锅包肉
//释放资源
delete pcmd1;
delete pcmd2;
delete pwaiter;
*/
/*
_nmsp1::Cook cook;
//一次性在便签上写下多道菜品
_nmsp1::Command* pcmd1 = new _nmsp1::CommandFish(&cook);
_nmsp1::Command* pcmd2 = new _nmsp1::CommandMeat(&cook);
_nmsp1::Waiter *pwaiter= new _nmsp1::Waiter();
//把多道菜品分别加入到菜品列表
pwaiter->AddCommand(pcmd1);
pwaiter->AddCommand(pcmd2);
//服务员一次性通知厨师做多道菜
pwaiter->Notify();
//释放资源
delete pcmd1;
delete pcmd2;
delete pwaiter;
*/
return 0;
}
```cpp
#include <iostream>
#include <list>
#ifdef _DEBUG //只在Debug(调试)模式下
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) //重新定义new运算符
#define new DEBUG_NEW
#endif
#endif
//#include <boost/type_index.hpp>
using namespace std;
//#pragma warning(disable : 4996)
namespace _nmsp1
{
//厨师类
class Cook
{
public:
//做红烧鱼
void cook_fish()
{
cout << "做一盘红烧鱼菜品" << endl;
}
//做锅包肉
void cook_meat()
{
cout << "做一盘锅包肉菜品" << endl;
}
//做其他各种菜品......略
};
//----------------------
//厨师做的每样菜品对应的抽象类
class Command
{
public:
Command(Cook* pcook)
{
m_pcook = pcook;
}
//做父类时析构函数为虚函数
virtual ~Command()
{
if (m_pcook != nullptr)
{
delete m_pcook;
m_pcook = nullptr;
}
}
virtual void Execute() = 0;
//virtual void Undo() = 0;
protected:
Cook* m_pcook; //子类需要访问
};
//做红烧鱼菜品命令
class CommandFish :public Command
{
public:
CommandFish(Cook* pcook) :Command(pcook) {}
virtual void Execute()
{
m_pcook->cook_fish();
}
};
//做锅包肉菜品命令
class CommandMeat :public Command
{
public:
CommandMeat(Cook* pcook) :Command(pcook) {}
virtual void Execute()
{
m_pcook->cook_meat(); //将一个动作封装成了一个对象
}
};
//服务员类
class Waiter
{
public:
//将顾客的便签增加到便签列表中,即便一个便签中包含多个菜品,这也相当于一道一道菜品加入到列表中
void AddCommand(Command* pcommand)
{
m_commlist.push_back(pcommand);
}
//如果顾客想撤单则将便签从列表中删除
void DelCommand(Command* pcommand)
{
m_commlist.remove(pcommand);
}
void Notify() //服务员将所有便签一次性交到厨师手里让厨师开始按顺序做菜
{
//依次让厨师做每一道菜品
for (auto iter = m_commlist.begin(); iter != m_commlist.end(); ++iter)
{
(*iter)->Execute();
}
}
private:
//一个便签中可以包含多个菜品甚至可以一次收集多个顾客的便签,达到一次性通知厨师做多道菜的效果
std::list<Command*> m_commlist; //菜品列表,每道菜品作为一项,如果一个便签中有多个菜品,则这里将包含多项
};
}
int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口
//下面new cook作为参数,是因为Command析构函数中增加了代码
_nmsp1::Command* pcmd1 = new _nmsp1::CommandFish(new _nmsp1::Cook());
_nmsp1::Command* pcmd2 = new _nmsp1::CommandMeat(new _nmsp1::Cook());
_nmsp1::Waiter *pwaiter= new _nmsp1::Waiter();
//把多道菜品分别加入到菜品列表
pwaiter->AddCommand(pcmd1);
pwaiter->AddCommand(pcmd2);
//服务员一次性通知厨师做多道菜
pwaiter->Notify();
//释放资源
delete pcmd1;
delete pcmd2;
delete pwaiter;
return 0;
}
UML:
Command(抽象命令类):抽象出命令对象,可以根据不同的命令类型。写出不同的实现类
ConcreteCommand(具体命令类):实现了抽象命令对象的具体实现
Invoker(调用者/请求者):请求的发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令来之间存在关联。在程序运行时,将调用命令对象的execute() ,间接调用接收者的相关操作。
Receiver(接收者):接收者执行与请求相关的操作,真正执行命令的对象。具体实现对请求的业务处理。未抽象前,实际执行操作内容的对象。
Client(客户端):在客户类中需要创建调用者对象,具体命令类对象,在创建具体命令对象时指定对应的接收者。发送者和接收者之间没有之间关系。都通过命令对象来调用。
参考链接:
命令模式