设计模式之命令模式

来源:互联网 发布:淘宝网官网电话 编辑:程序博客网 时间:2024/06/05 11:55

命令模式将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其它对象。命令模式也支持可撤销的操作。通过定义一个统一的抽象Command类,这个类声明了两个纯虚函数(如果要加入日志等功能也可以再追加),一个是请求命令函数execute(),另一个是撤销命令函数undo(),然后所有的具体命令都继承自这个Command类,具体命令中包含了实现具体动作的对象(receiver)的引用或指针,具体命令需要重写execute()函数,在里面加入receiver的具体动作,同时在重写的undo里面加入receiver对应的撤销动作。这样客户类只需要保留一个指向Command对象的引用或指针,然后通过调用Comand的两个函数,就能实现相应的动作,而不用关心具体命令的实现以及命令动作的实现对象,即实现了动作请求和执行对象的解耦。

命令模式的类图如下:


下面通过设计一个遥控器的具体实例,来说明命令模式的使用:该遥控器实现了电灯、音响的开关命令和各自的撤销,具体程序如下:

#include "stdafx.h"#include <iostream>#include <vector>#include <memory>#include <string>using namespace std;//命令接收者(类图中的receiver)class Light {public :Light(string location) {this->location = location;}void on() {cout<<location<<" light is on"<<endl;}void off() {cout<<location<<" light is off"<<endl;}private:string location;};//命令接收者(类图中的receiver)class Stereo {private:string location;public:Stereo(string location) {this->location = location;}void on() {cout<<location<<" stereo is on"<<endl;}void off() {cout<<location <<" stereo is off"<<endl;}void setCD() {cout<<location <<" stereo is set for CD input"<<endl;}void setVolume(int volume) {cout<<location <<" Stereo volume set to "<<volume<<endl;}};//抽象命令接口类class Command {public: virtual void execute()=0;virtual void undo()=0;};//默认命令对象class NoCommand :public Command {public :void execute() { cout<<"There is not a valid command"<<endl;}void undo(){cout<<"There is not a valid command"<<endl;}};//具体命令对象class LightOnCommand :public Command {private:shared_ptr<Light> light;public:LightOnCommand(shared_ptr<Light>light) {this->light = light;}void execute() {light->on();}void undo(){light->off();}};//具体命令对象class LightOffCommand  :public Command {private:shared_ptr<Light> light;public:LightOffCommand (shared_ptr<Light> light) {this->light = light;}void execute() //请求动作{light->off();}void undo()  //撤销动作{light->on();}};//具体命令对象class StereoOnWithCDCommand:public Command {private:shared_ptr<Stereo> stereo;public:StereoOnWithCDCommand(shared_ptr<Stereo> stereo) {this->stereo = stereo;}void execute() {stereo->on();stereo->setCD();stereo->setVolume(11);}void undo(){stereo->off();}};//具体命令对象class StereoOffCommand :public Command {private:shared_ptr<Stereo> stereo;public:StereoOffCommand (shared_ptr<Stereo> stereo) {this->stereo = stereo;}void execute() {stereo->off();}void undo(){stereo->on();stereo->setCD();stereo->setVolume(11);}};//客户(即类图中client)class RemoteControl {private:vector<shared_ptr<Command>> onCommands;  //实现多个开命令(命令对象指针或引用)vector<shared_ptr<Command>> offCommands;  //实现多个关命令(命令对象指针或引用)public:RemoteControl() {onCommands=vector<shared_ptr<Command>>(2,nullptr);offCommands =vector<shared_ptr<Command>>(2,nullptr);//给命令对象赋默认值shared_ptr<Command> noCommand=shared_ptr<Command>(new NoCommand);for (int i = 0; i < 2; i++) {onCommands[i] = noCommand;offCommands[i] = noCommand;}}//设置命令对象void setCommand(int slot, shared_ptr<Command> onCommand, shared_ptr<Command> offCommand) {onCommands[slot] = onCommand;offCommands[slot] = offCommand;}void onButtonWasPushed(int slot) {onCommands[slot]->execute();}void offButtonWasPushed(int slot) {offCommands[slot]->execute();}void undoButtonWasPushed(int slot){offCommands[slot]->undo();}};int _tmain(int argc, _TCHAR* argv[]){RemoteControl remoteControl ;shared_ptr<Light> kitchenLight=shared_ptr<Light>(new Light("Kitchen"));shared_ptr<LightOnCommand> kitchenLightOn =shared_ptr<LightOnCommand>(new LightOnCommand(kitchenLight));shared_ptr<LightOffCommand> kitchenLightOff = shared_ptr<LightOffCommand>(new LightOffCommand(kitchenLight));shared_ptr<Stereo> stereo=shared_ptr<Stereo>(new Stereo("Living Room"));shared_ptr<StereoOnWithCDCommand> stereoOnWithCD =shared_ptr<StereoOnWithCDCommand>(new StereoOnWithCDCommand(stereo));shared_ptr<StereoOffCommand> stereoOff =shared_ptr<StereoOffCommand>(new StereoOffCommand(stereo));remoteControl.setCommand(0, kitchenLightOn, kitchenLightOff);remoteControl.setCommand(1, stereoOnWithCD, stereoOff);remoteControl.onButtonWasPushed(0);remoteControl.offButtonWasPushed(0);remoteControl.undoButtonWasPushed(0);remoteControl.onButtonWasPushed(1);remoteControl.offButtonWasPushed(1);remoteControl.undoButtonWasPushed(1);return 0;}
程序执行结果如下:



0 0
原创粉丝点击