命令模式(Command):
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
命令模式代码:
#pragma once
#include <string>
#include <iostream>
using namespace std;
//Receive类,知道如何实施于执行一个与请求相关的类的操作,任何类都可能作为一个接受者。
class CReceiver
{
public:
void Action()
{
cout<<"command"<<endl;
}
};
//Command类,用来声明执行操作的接口。
class CCommand
{
protected:
CReceiver *m_pReceiver;
public:
CCommand(CReceiver *pReceiver)
{
m_pReceiver = pReceiver;
}
virtual void Execute() = 0;
};
//ConcreteCommand类,将一个接收者对象绑定于一个动作,调用接收者响应的操作,以实现Execute.
class CConcreteCommand : public CCommand
{
public:
CConcreteCommand(CReceiver *pReceiver) :CCommand(pReceiver)
{
}
void Execute()
{
m_pReceiver->Action();
}
};
//Invoker类,要求该命令执行这个请求。
class CInvoker
{
private:
CCommand *m_pCommand;
public:
void SetCommand(CCommand *pCommand)
{
m_pCommand = pCommand;
}
void ExecuteCommand()
{
m_pCommand->Execute();
}
};
客户端调用代码:
#include "stdafx.h"
#include "CommandMode.h"
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
CReceiver *p_Receiver = new CReceiver();
CCommand *p_Command = new CConcreteCommand(p_Receiver);
CInvoker *p_Invoker = new CInvoker();
p_Invoker->SetCommand(p_Command);
p_Invoker->ExecuteCommand();
delete p_Receiver;
delete p_Command;
delete p_Invoker;
return 0;
}
执行结果:总结:
设计模式的优点:
1.它能较容易地设计一个命令队列;
2.在需要的情况下,可以较容易地将命令计入日志;
3.允许接收请求的一方决定是否要否决请求;
4.可以容易地实现对请求的撤销和重做;
5.由于加进新的具体命令类不影响其他的类,因此增加新的具体命令很容易。
6.最重要的一点是命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。
敏捷开发原则:
不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不要急着去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。
最后为了方便理解,用饭店点菜的逻辑来描述这个模式
Command 做菜
ConcreteCommand 做烤鱼
Receiver 厨师
Invoker 服务员
Client 客户
描述一下主函数使用:
CReceiver *p_Receiver = new CReceiver(); 定义一个烤鱼厨师。
CCommand *p_Command = new CConcreteCommand(p_Receiver);定义一个命令,是烤鱼,并且把师傅设定为烤鱼厨师。
CInvoker *p_Invoker = new CInvoker();定义一个服务员。
p_Invoker->SetCommand(p_Command); 给服务员说一个请求。
p_Invoker->ExecuteCommand(); 服务员去干活了。