模式六:命令模式(Command Pattern)——封裝請求物件
阿新 • • 發佈:2019-02-15
命令模式
將“請求”封裝成物件,以便使用不同的請求、佇列或者日誌來引數化其他物件。命令模式也支援可撤銷的操作。
應用分析
命令模式的設計,定義公共的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;
}