设计模式(行为型模式)(命令模式)

命令模式

#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(客户端):在客户类中需要创建调用者对象,具体命令类对象,在创建具体命令对象时指定对应的接收者。发送者和接收者之间没有之间关系。都通过命令对象来调用。

参考链接:
命令模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lz_煜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值