#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;
}