命令模式:将一个请求封装成一个对象,从而允许你使用不同的请求,队列或者日志将客户端参数化,同时支持请求操作的撤销与恢复;
主要目的
该设计模式主要是为了隔离请求和实际执行者之间接触,实现两者的解耦。所有的请求统一有一个类负责
该类负责管理这些请求。这样命令对象和接收者之间的耦合度就会降低。命令对象不用直接施加命令到接收者上。
而会通过施加命令到命令接口,通过命令接口实例化出来一个相应的命令,从而施加到接收者上。
具体例子:
1.我们去餐厅吃饭,我们是通过服务员来点菜,具体是谁来做这些菜和他们什么时候完成的这些菜,其实我们都不知道。抽象之,我们是“菜单请求者”,厨师是“菜单实现者”,2者之间是松耦合的,我们对这些菜的其他一些请求比如“撤销,重做”等,我们也不知道是谁在做。其实这就是本文要说的Command模式。将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。[GOF 《设计模式》]
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#define SAFE_DELETE(p) if (p) { delete p; p = NULL; }//安全删除
//烧烤师傅类,最后的执行者
class Barbecuer
{
public:
void BakeMutton()
{
cout << "Bake Mutton" << endl;
}
void BakeChickenWing()
{
cout << "Bake ChickenWing" << endl;
}
};
//抽象命令类:执行具体操作的接口
class Command
{
public:
Command() {};
Command(Barbecuer* receiver):p_receiver(receiver) {}
virtual void ExecuteCommand() = 0;
protected:
Barbecuer* p_receiver;
};
//具体命令,烤羊肉串命令
class BakeMuttonCommand:public Command
{
public :
BakeMuttonCommand(Barbecuer* receiver)
{
p_receiver = receiver;
}
void ExecuteCommand()
{
p_receiver->BakeMutton();
}
};
//具体命令,烤鸡翅命令
class BakeChickenWingCommand :public Command
{
public:
BakeChickenWingCommand(Barbecuer* receiver)
{
p_receiver=receiver;
}
void ExecuteCommand()
{
p_receiver->BakeChickenWing();
}
};
//服务员类,相当于命令者
class Waiter
{
public:
void SetOrder(Command* command);//相当于一个命令队列
void Notify();
private:
vector<Command*>p_Commandlist;
};
//按照顺序给队列内添加相应的命令
void Waiter::SetOrder(Command* command)
{
p_Commandlist.push_back(command);
cout << "增加烤肉命令" << endl;
}
//按顺序执行所有命令
void Waiter::Notify()
{
vector<Command*>::iterator i;
for (i = p_Commandlist.begin(); i < p_Commandlist.end(); ++i)
{
(*i)->ExecuteCommand();
}
}
int main(int argc, char* argv[])
{
//生成订单,烧烤师傅,服务员
Barbecuer* p_cook = new Barbecuer();
Command* p_mutton = new BakeMuttonCommand(p_cook);
Command* p_chicken = new BakeChickenWingCommand(p_cook);
Waiter* p_waiter = new Waiter();
//将顶点添加到队列中
p_waiter->SetOrder(p_mutton);
p_waiter->SetOrder(p_chicken);
//服务员通知订单开始执行
p_waiter->Notify();
SAFE_DELETE(p_cook);
SAFE_DELETE(p_mutton);
SAFE_DELETE(p_chicken);
SAFE_DELETE(p_waiter);
return 0;
}
2.单人回合制的游戏中,我们想让玩家能够撤销一些行动一边能够更多专注与策略而不是猜测。我们可以将所有的动作封装起来。
伪代码如下:
class Command
{
public:
virtual ~Command() {}
virtual void execute() = 0;
virtual void undo() = 0;
};
class MoveUnitCommand : public Command
{
public:
MoveUnitCommand(Unit* unit, int x, int y)
: unit_(unit),
xBefore_(0),
yBefore_(0),
x_(x),
y_(y)
{}
virtual void execute()
{
// 保存移动之前的位置
// 这样之后可以复原。
xBefore_ = unit_->x();
yBefore_ = unit_->y();
unit_->moveTo(x_, y_);
}
virtual void undo()
{
unit_->moveTo(xBefore_, yBefore_);
}
private:
Unit* unit_;
int xBefore_, yBefore_;
int x_, y_;
};
参考资料:《游戏编程模式》,《设计模式》