C++设计模式七--CommandPattern(命令模式)

来源:互联网 发布:手机zip解压软件 编辑:程序博客网 时间:2024/06/01 09:55

定义

  命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。

要点

  1)命令模式将调用者接受者对象解耦。
  2)被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接受者和一个或者一组动作
  3)调用者通过调用命令对象的execute()发出请求,这会使得接收者的动作被调用。
  4)调用者可以接受命令对象当做参数,甚至在运行时动态地进行。
  5)命令可以支持撤销,做法是实现一个undo()方法来回到execute()倍执行前的状态。
  6)命令可以用来实现日志事务系统

类图

这里写图片描述
Invoker:调用者持有一个命令对象,并在某个时间点调用命令对象的execute()方法,将请求付诸行动。
Command:为所有命令声明一个接口。调用命令对象的execute()方法,就可以就可以让接收者进行相关的动作。这个接口也具备一个undo()方法。
Receiver:接收者知道如何进行必要的工作,实现这个请求。任何类都可以做接收者。

示例

  下面模拟一个遥控器程序,来控制电灯和音响的开关。
Light.h

#ifndef LIGHT_H#define LIGHT_H#include <string>#include <iostream>using std::string;using std::cout;using std::endl;// 灯(Receiver)class Light{public:    Light(string n): name(n)    {}    ~Light(){}    void on()    {        cout << name << " is on" << endl;    }    void off()    {        cout << name << " is off" << endl;    }private:    string name;};#endif

Stereo.h

#ifndef STEREO_H#define STEREO_H#include <string>#include <iostream>using std::string;using std::cout;using std::endl;// 音响(Receiver)class Stereo{public:    Stereo(string n): name(n)    {}    ~Stereo(){}    void on()    {        cout << name << " is on" << endl;    }    void off()    {        cout << name << " is off" << endl;    }private:    string name;};#endif

Command.h

#ifndef COMMAND_H#define COMMAND_H#include "Light.h"#include "Stereo.h"// 命令接口class Command{public:    Command(){}    virtual~Command(){}    virtual void execute() = 0;    virtual void undo() = 0;};// 空命令class NoCommand : public Command {public:    NoCommand(){}    ~NoCommand(){}    void execute(){}    void undo(){}};// 开灯命令class LightOnCommand: public Command{public:    LightOnCommand(Light *l): light(l)    {    }    ~LightOnCommand(){}    void execute()    {        light->on();    }    void undo()    {        light->off();    }private:    Light *light;};// 关灯命令class LightOffCommand: public Command{public:    LightOffCommand(Light *l): light(l)    {    }    ~LightOffCommand(){}    void execute()    {        light->off();    }    void undo()    {        light->on();    }private:    Light *light;};// 开音响命令class StereoOnCommand: public Command{public:    StereoOnCommand(Stereo *s): stereo(s)    {    }    ~StereoOnCommand(){}    void execute()    {        stereo->on();    }    void undo()    {        stereo->off();    }private:    Stereo *stereo;};// 关音响命令class StereoOffCommand: public Command{public:    StereoOffCommand(Stereo *s): stereo(s)    {    }    ~StereoOffCommand(){}    void execute()    {        stereo->off();    }    void undo()    {        stereo->on();    }private:    Stereo *stereo;};// 遥控器(Invoker)class RemoteControl {private:    Command* onCommands[7];    // 最多控制7个设备    Command* offCommands[7];    Command* undoCommand;    Command* noCommand;public:    RemoteControl()    {        noCommand = new NoCommand();        for (int i=0; i<7; i++) {            onCommands[i] = noCommand;            offCommands[i] = noCommand;        }        undoCommand = noCommand;    }    ~RemoteControl()        {            delete noCommand;        }    void setCommand(int slot, Command* onCommand, Command* offCommand)    {        onCommands[slot] = onCommand;        offCommands[slot] = offCommand;    }    void onButtonWasPushed(int slot)    {        onCommands[slot]->execute();        undoCommand = onCommands[slot];    }    void offButtonWasPushed(int slot)    {        offCommands[slot]->execute();        undoCommand = offCommands[slot];    }    void undoButtonWasPushed()    {        undoCommand->undo();    }};// 批量命令(Invoker)class MacroCommand: public Command{private:    Command** command;    int cnt;public:    MacroCommand(Command** cmd, int c): command(cmd), cnt(c)    {    }    ~MacroCommand(){}    void execute()    {        for (int i=0; i<cnt; i++) {            command[i]->execute();        }    }    void undo()    {       for (int i=0; i<cnt; i++) {            command[i]->undo();        }    }};#endif

main.cpp

#include "Command.h"int main(){    Light *light = new Light("Simple light");    Stereo *stereo = new Stereo("Cool stereo");    LightOnCommand *loc = new LightOnCommand(light);    LightOffCommand *lofc = new LightOffCommand(light);    StereoOnCommand *soc = new StereoOnCommand(stereo);    StereoOffCommand *sofc = new StereoOffCommand(stereo);    RemoteControl* remoteControl = new RemoteControl();    remoteControl->setCommand(0, loc, lofc);    remoteControl->setCommand(1, soc, sofc);    remoteControl->onButtonWasPushed(0);    remoteControl->offButtonWasPushed(0);    remoteControl->onButtonWasPushed(1);    remoteControl->offButtonWasPushed(1);    remoteControl->undoButtonWasPushed();    cout << "==============================" << endl;    Command* cmd[2] = {loc, soc};    MacroCommand* macroCommand = new MacroCommand(cmd, 2);    macroCommand->execute();    macroCommand->undo();    delete macroCommand;    delete remoteControl;    delete sofc;    delete soc;    delete lofc;    delete loc;    delete stereo;    delete light;    return 0;}

Makefile

CXX = g++CFLAGS = -WallLDFLAGS = target = ressrcs = main.cppobjs = $(srcs:.cpp=.o)headers = $(wildcard *.h).PHONY: allall: $(target)$(target): $(objs) $(headers)    $(CXX) $(LDFLAGS) -o $(target) $(objs)$(objs):%.o:%.cpp    $(CXX) $(CFLAGS) -c -o $@ $<clean:    rm -f $(target) *.o

测试

测试结果如下图所示:
这里写图片描述

原创粉丝点击