设计模式之命令模式

    xiaoxiao2025-04-30  8

    命令模式将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其它对象。命令模式也支持可撤销的操作。通过定义一个统一的抽象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; } 程序执行结果如下:

    转载请注明原文地址: https://ju.6miu.com/read-1298619.html
    最新回复(0)