命令模式
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
示例代码
//命令模式
//Receiver 类。知道如何实现与执行一个与请求相关的操作,任何类都可能作为一个接收者
class Receiver
{
public:
void Action(){ cout << "执行请求" << endl; }
};
//Command 类,用来声明执行操作的接口
class Command
{
public:
Command(Receiver receiver):m_receiver(receiver){}
virtual void Execute() = 0;
protected:
Receiver m_receiver;
};
//ConcreteCommand类,将一个接收者对象绑定于一个动作,以实现 Excute
class ConcreteCommand:public Command
{
public:
ConcreteCommand(Receiver receiver) :Command(receiver){}
void Execute(){ m_receiver.Action(); }
};
//Invoker 类,要求该命令执行这个请求
class Invoker
{
public:
void SetCommand(Command *command){ m_command = command; }
void ExecuteCommand(){ m_command->Execute(); }
private:
Command *m_command;
};
int main()
{
Receiver r;
Command *c = new ConcreteCommand(r);
Invoker i;
i.SetCommand(c);
i.ExecuteCommand();
system("pause");
return 0;
}
命令模式作用
- 它能较容易地设计一个命令队列;
- 在需要的情况下,可以较容易地将命令记入日志;
- 允许接收请求的一方决定是否要否决决策;
- 可以容易地实现对请求的撤销和重做;
- 由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。
- 命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。
敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。
命令模式实例 – 烤串
//命令模式实例 -- 烤串
//烤肉串者
class Barvecuer
{
public:
void BakeMutton(){ cout << "烤羊肉串" << endl; }
void BakeChickenWing(){ cout << "烤鸡翅" << endl; }
};
//抽象命令 只需要确定要通知谁执行命令 即烤串者 为烤羊肉串和烤鸡翅命令做一个统一接口
class Command
{
public:
Command(Barvecuer receiver):m_receiver(receiver){}
virtual void ExecuteCommand() = 0;
protected:
Barvecuer m_receiver;
};
//烤羊肉串命令
class BakeMuttonCommand :public Command
{
public:
BakeMuttonCommand(Barvecuer receiver):Command(receiver){}
void ExecuteCommand(){ m_receiver.BakeMutton(); }
};
//烤鸡翅命令
class BakeChickenWingCommand :public Command
{
public:
BakeChickenWingCommand(Barvecuer receiver) :Command(receiver){}
void ExecuteCommand(){ m_receiver.BakeChickenWing(); }
};
//服务员 只需要记录命令和通知执行命令
class Waiter
{
public:
//设置订单,即设置命令
void SetOrder(Command *command)
{
m_order.push_back(command);
cout << "增加订单..." <<endl;
}
void CancleOrder(Command *command)
{
m_order.remove(command);
cout << "取消订单..." << endl;
}
//通知执行者执行
void Notify()
{
cout << "订单为:" << endl;
for (const auto &n : m_order)
{
n->ExecuteCommand();
}
}
private:
list<Command*> m_order;
};
int main()
{
Barvecuer zzz; //烤串者zzz
Command *bakeMuttonCommand1 = new BakeMuttonCommand(zzz);
Command *bakeMuttonCommand2 = new BakeMuttonCommand(zzz);
Command *bakeChickenCommand1 = new BakeChickenWingCommand(zzz);
Waiter girl;
//第一个订单 烤羊肉串
girl.SetOrder(bakeMuttonCommand1);
//第二个订单 烤羊肉串
girl.SetOrder(bakeMuttonCommand2);
//第三个订单 烤鸡翅
girl.SetOrder(bakeChickenCommand1);
//取消订单
girl.CancleOrder(bakeMuttonCommand2);
girl.Notify();
system("pause");
return 0;
}