C++命令模式(Command)

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值