zoukankan      html  css  js  c++  java
  • c++设计模式:命令模式(Command Pattern)

    定义:

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

    场景:

    我们要设计一个遥控器,可以通过按动上边的控制按钮控制卧室和厨房的灯,还能控制卧室中的音响的开关。遥控器及时我们的“动作的请求者”,而灯和音响就是我们的“动作的执行者”。当我们按动遥控器上的某个开关后,遥控器就可以把相关的指令发送到我们的指定的家电上。这之中遥控器和家电之间是解耦的,我们完全可以通过设置,添加、修改或删除其它的家电控制功能,而不需要修改遥控器的代码。

    类图:

    c++代码如下:

    #include <iostream>
    #include <vector>
    using namespace std;

    class Command
    {
    public:
    virtual void execute() = 0;
    };

    class NoCommand : public Command
    {
    public:
    void execute() {};
    };

    class Light
    {
    public:
    Light(string location);
    void on();
    void off();
    private:
    string m_sLocation;
    };

    class LightOffCommand : public Command
    {
    public:
    LightOffCommand(string location):m_Light(location) {}
    void execute();
    private:
    Light m_Light;
    };

    class LightOnCommand : public Command
    {
    public:
    LightOnCommand(string location):m_Light(location) {}
    void execute();
    private:
    Light m_Light;
    };

    class Stereo
    {
    public:
    Stereo(string location);
    void on();
    void off();
    void setCD();
    void setDVD();
    void setRadio();
    void setVolume(int volume);
    private:
    string m_sLocation;
    };

    class StereoOnWithCDCommand : public Command
    {
    public:
    StereoOnWithCDCommand(string location):m_Stereo(location) {}

    void execute();
    private:
    Stereo m_Stereo;
    };

    class StereoOffCommand : public Command
    {
    public:
    StereoOffCommand(string location):m_Stereo(location) {}

    void execute();
    private:
    Stereo m_Stereo;
    };

    class RemoteControl
    {
    public:
    RemoteControl();
    ~RemoteControl();
    void setCommand(int slot, Command* pOnCommand, Command* pOffCommand);
    void onButtonWasPushed(int slot);
    void offButtonWasPushed(int slot);
    private:
    vector<Command*> m_OnCommands;
    vector<Command*> m_OffCommands;
    };

    Light::Light(string location)
    {
    m_sLocation = location;
    }

    void Light::on()
    {
    printf("%s light is on\n",m_sLocation.c_str());
    }

    void Light::off()
    {
    printf("%s light is off\n",m_sLocation.c_str());
    }

    void LightOffCommand::execute()
    {
    m_Light.off();
    }

    void LightOnCommand::execute()
    {
    m_Light.on();
    }

    Stereo::Stereo(string location)
    {
    m_sLocation = location;
    }

    void Stereo::on()
    {
    printf("%s stereo is on\n",m_sLocation.c_str());
    }

    void Stereo::off()
    {
    printf("%s stereo is off\n",m_sLocation.c_str());
    }

    void Stereo::setCD()
    {
    printf("%s stereo is set for CD input\n",m_sLocation.c_str());
    }

    void Stereo::setDVD()
    {
    printf("%s stereo is set for DVD input\n",m_sLocation.c_str());
    }

    void Stereo::setRadio()
    {
    printf("%s stereo is set for Radio\n",m_sLocation.c_str());
    }

    void Stereo::setVolume(int volume)
    {
    printf("%s Stereo volume set to %d\n",m_sLocation.c_str(),volume);
    }

    void StereoOnWithCDCommand::execute()
    {
    m_Stereo.on();
    m_Stereo.setCD();
    m_Stereo.setVolume(11);
    }

    void StereoOffCommand::execute()
    {
    m_Stereo.off();
    }

    RemoteControl::RemoteControl()
    {
    for (int i = 0; i < 7; i++)
    {
    Command* noCommandOn = new NoCommand();
    m_OnCommands.push_back(noCommandOn);
    Command* noCommandOff = new NoCommand();
    m_OffCommands.push_back(noCommandOff);
    }
    }

    RemoteControl::~RemoteControl()
    {
    for (int i = 0; i < 7; i++)
    {
    delete m_OnCommands.at(i);
    delete m_OffCommands.at(i);
    }
    m_OnCommands.clear();
    m_OffCommands.clear();
    }

    void RemoteControl::setCommand(int slot, Command* pOnCommand, Command* pOffCommand)
    {
    delete m_OnCommands.at(slot);
    m_OnCommands.at(slot) = pOnCommand;
    delete m_OffCommands.at(slot);
    m_OffCommands.at(slot) = pOffCommand;
    }

    void RemoteControl::onButtonWasPushed(int slot)
    {
    m_OnCommands.at(slot)->execute();
    }

    void RemoteControl::offButtonWasPushed(int slot)
    {
    m_OffCommands.at(slot)->execute();
    }

    int main()
    {
    RemoteControl remoteControl;
    LightOffCommand* pLivingRoomLightOff = new LightOffCommand("Living Room");
    LightOffCommand* pKitchenLightOff = new LightOffCommand("Kitchen");
    LightOnCommand* pLivingRoomLightOn = new LightOnCommand("Living Room");
    LightOnCommand* pKitchenLightOn = new LightOnCommand("Kitchen");
    StereoOnWithCDCommand* pStereoOnWithCD = new StereoOnWithCDCommand("Living Room");
    StereoOffCommand* pStereoOff = new StereoOffCommand("Living Room");

    remoteControl.setCommand(0,pLivingRoomLightOn,pLivingRoomLightOff);
    remoteControl.setCommand(1,pKitchenLightOn,pKitchenLightOff);
    remoteControl.setCommand(2,pStereoOnWithCD,pStereoOff);

    remoteControl.onButtonWasPushed(0);
    remoteControl.offButtonWasPushed(0);
    remoteControl.onButtonWasPushed(1);
    remoteControl.offButtonWasPushed(1);
    remoteControl.onButtonWasPushed(2);
    remoteControl.offButtonWasPushed(2);
    return 0;
    }

    运行结果如下:

    Living Room light is on

    Living Room light is off

    Kitchen light is on

    Kitchen light is off

    Living Room stereo is on

    Living Room stereo is set for CD input

    Living Room Stereo volume set to 11

    Living Room stereo is off

    参考图书:《Head First 设计模式》



  • 相关阅读:
    搭建angularjs API文档站点
    Web网站数据”实时”更新设计
    3kb jQuery代码搞定各种树形选择。
    阿里妈妈自动登录程序
    Android中RelativeLayout属性详细说明
    jQuery选择器总结
    ajax页面加载进度条插件
    jquery ajax 方法及各参数详解
    使用jQuery加载html页面到指定的div
    C#中无边框窗体移动
  • 原文地址:https://www.cnblogs.com/osyun/p/2317184.html
Copyright © 2011-2022 走看看