命令模式
将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
应用分析
命令模式的设计,定义公共的Command接口,使请求调用者和请求接收者之间解耦,便于请求扩展。
Command:定义命令的统一接口
ConcreteCommand:Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。
Receiver:命令的实际执行者
Invoker:命令的请求者,是命令模式中最重要的角色。这个角色用来对各个命令进行控制。
实例分析
用一个遥控器控制不同电器,执行不同操作,比如:灯的开关、电视机的开关等,这样,我们可以将最终的接收者灯和电视的行为封装成命令对象,通过命令对象的统一接口execute执行相关操作。
代码分析
//Command.h
//Command接口
#ifndef COMMAND_H
#define COMMAND_H
#include <iostream>
class Command
{
public:
virtual void execute()=0;
virtual void undo()=0;
virtual ~Command(){}
};
class NoCommand:public Command
{
public:
void execute()
{
std::cout<<"Nothing on"<<std::endl;
}
void undo()
{
std::cout<<"Nothing off"<<std::endl;
}
};
#endif
//Receiver.h
//接收者
#ifndef RECEIVER_H
#define RECEIVER_H
#include <iostream>
class Light
{
public:
void on()
{
std::cout<<"Light on"<<std::endl;
}
void off()
{
std::cout<<"Light off"<<std::endl;
}
};
class TV
{
public:
void on()
{
std::cout<<"TV on"<<std::endl;
}
void off()
{
std::cout<<"TV off"<<std::endl;
}
};
#endif
//ConcreteCommand.h
//命令实体对象
#ifndef COMCRETECOMMAND_H
#define COMCRETECOMMAND_H
#include "Command.h"
#include "Receiver.h"
class OnTVCommand:public Command
{
private:
TV &TVReceive;
public:
OnTVCommand(TV & TVre):TVReceive(TVre){}
void execute()
{
TVReceive.on();
}
void undo()
{
TVReceive.off();
}
};
class OffTVCommand:public Command
{
private:
TV &TVReceive;
public:
OffTVCommand(TV & TVre):TVReceive(TVre){}
void execute()
{
TVReceive.off();
}
void undo()
{
TVReceive.on();
}
};
class OnLightCommand:public Command
{
private:
Light &LightReceiver;
public:
OnLightCommand(Light &LightRe):LightReceiver(LightRe){}
void execute()
{
LightReceiver.on();
}
void undo()
{
LightReceiver.off();
}
};
class OffLightCommand:public Command
{
private:
Light &LightReceiver;
public:
OffLightCommand(Light &LightRe):LightReceiver(LightRe){}
void execute()
{
LightReceiver.off();
}
void undo()
{
LightReceiver.on();
}
};
#endif
//Invoker.h
//调用者
#ifndef INVOKER_H
#define INVOKER_H
#include "Command.h"
class Command;
NoCommand noCommand;
class Invoker
{
private:
Command * undoCommand;
Command * onCommands[7];
Command * offCommands[7];
public:
Invoker()
{
for(int i=0;i<7;++i)
{
onCommands[i]=&noCommand;
offCommands[i]=&noCommand;
}
undoCommand=&noCommand;
}
void setCommand(int slot,Command & onCommand,Command & offCommand)
{
onCommands[slot]=&onCommand;
offCommands[slot]=&offCommand;
}
void onButton(int slot)
{
onCommands[slot]->execute();
undoCommand=onCommands[slot];
}
void offButton(int slot)
{
offCommands[slot]->execute();
undoCommand=offCommands[slot];
}
void undo()
{
undoCommand->undo();
}
};
#endif
//Main.cpp
//测试程序
#include "ConcreteCommand.h"
#include "Invoker.h"
int main()
{
TV tv;
Light light;
OnTVCommand ontvCommand(tv);
OffTVCommand offtvCommand(tv);
OnLightCommand onlightCommand(light);
OffLightCommand offlightCommand(light);
Invoker invoker;
invoker.setCommand(0,ontvCommand,offtvCommand);
invoker.setCommand(1,onlightCommand,offlightCommand);
invoker.onButton(0);
invoker.offButton(1);
invoker.onButton(3);
invoker.onButton(1);
invoker.undo();
return 0;
}