【C++设计模式】命令模式

#ifndef __COMMAND_H__
#define __COMMAND_H__

#include <iostream>
#include <list>

//【说明】
// 命令模式是为了解决命令的请求者和命令的实现者之间的耦合关系。
// Command对象在执行命令时,并不一定自己切身做这件事,而是将请求转发给另一个真正做这件事情的对象(Receiver对象),由Receiver对象最终完成请求操作。

//【定义】
// 命令模式(Command):把一个请求或者操作封装到一个对象中。从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持撤销和恢复功能。

//【角色】
// 命令(Command)角色:声明了一个给所有具体命令类的抽象接口。
// 具体命令(ConcreteCommand)角色:定义一个接收者和行为之间的弱耦合;实现execute()方法,负责调用接收者的相应操作。
// 接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。
// 请求者(Invoker)角色:负责调用命令对象执行请求。
// 客户端(Client)角色:创建一个具体命令(ConcreteCommand)对象并确定其接收者。

//【意义】
// 松散的耦合,命令模式使得命令的发起对象和执行对象完全解耦,可以更方便的对命令进行扩展。
// 可以更容易的实现对多个命令的统一控制,这种控制包括但不限于:队列、撤销/恢复、记录日志等等。

//【示例】


//Command类,用来声明执行操作的接口
class iCommand
{
public:
	iCommand(){ }

	virtual ~iCommand(){ }

public:
	virtual void execute() = 0;
};

//Receiver类,真正执行请求相关操作的接口,任何类都可能作为一个接收者。
class iReceiver
{
public:
	iReceiver(){ }

	virtual ~iReceiver(){ }

public:
	virtual void execute() = 0;
};

//播放音乐命令
class PlayCommand : public iCommand
{
public:
	PlayCommand(iReceiver * recv) : m_recv(recv){ }

	virtual void execute();
private:
	iReceiver *m_recv;
};

//烹饪命令
class CookCommand : public iCommand
{
public:
	CookCommand(iReceiver * recv) : m_recv(recv){ }

	virtual void execute();
private:
	iReceiver *m_recv;
};

//播放器
class MediaPlayer : public iReceiver
{
public:
	virtual void execute();
};

//厨师
class Chef : public iReceiver
{
public:
	virtual void execute();
};

//如果客户端需要多种命令能够按照某个队列依次执行,我们需要把命令的执行者从客户端中分离出来。
//引入一个对象叫调度者,Invoker类,来控制命令的队列化和可撤销操作等,对命令进行管理。
class Invoker
{
public:
	void AddCommand(iCommand * cmd);

	int  ExecuteCommand();

	void CancelCommand(iCommand * com);

	void RollbackCommand(iCommand * com);

private:	
	std::list<iCommand*> m_cmdlist;
	std::list<iCommand*> m_historycmdlist;
};

void TestCommand();

#endif

#include "Command.h"

void PlayCommand::execute()
{
	m_recv->execute();
}

void CookCommand::execute()
{
	m_recv->execute();
}

void MediaPlayer::execute()
{
	printf("start play music.\n");
}

void Chef::execute()
{
	printf("start cook.\n");
}

void Invoker::AddCommand(iCommand* cmd)
{
	m_cmdlist.push_back(cmd);
}

int Invoker::ExecuteCommand()
{
	if (!m_cmdlist.empty())
	{
		iCommand * cmd = NULL;

		cmd = m_cmdlist.front();

		cmd->execute();

		m_cmdlist.pop_front();

		m_historycmdlist.push_back(cmd);
	}

	return -1;
}

void Invoker::CancelCommand(iCommand *com)
{
	//遍历命令队列,找到命令并删除
}

void Invoker::RollbackCommand(iCommand *com)
{
	//找到历史命令,并执行状态还原
}

void TestCommand()
{
	iReceiver * chef   = new Chef();

	iCommand * cookcmd = new CookCommand(chef);

	iReceiver * player = new MediaPlayer();

	iCommand * playcmd = new PlayCommand(player);

	Invoker * inv = new Invoker();

	inv->AddCommand(playcmd);

	inv->AddCommand(cookcmd);

	inv->ExecuteCommand();

	inv->ExecuteCommand();

	delete inv;
	delete chef;
	delete cookcmd;
	delete player;
	delete playcmd;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值