c++设计模式:命令模式(Command Pattern)

摘要:
定义:命令模式将“请求”封装到对象中,以便可以使用不同的请求、队列或日志来参数化其他对象。命令模式还支持可撤销操作。命令模式将“动作的请求者”与“动作的执行者”对象分离。场景:我们需要设计一个遥控器,它可以通过按下顶部的控制按钮来控制卧室和厨房的灯光,还可以控制卧室中立体声的开关。遥控器是我们的“行动请求者”,灯光和声音是我们的行动执行者。当我们按下遥控器上的开关时,遥控器可以

定义:

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

场景:

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

类图:

c++设计模式:命令模式(Command Pattern)第1张

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 设计模式》



免责声明:文章转载自《c++设计模式:命令模式(Command Pattern)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇前端面试题(1)winxp注册表之开始菜单和任务栏下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

VB创建类模块DLL文件

最近需要调用MSCOMM32.OCX控件,但是ABAP调用过程中发现无法同时发送多条记录,则需调整实现方式:   a.创建DLL文件封装MSCOMM控件相关属性及方法   b.系统注册DLL文件   c.ABAP调用DLL文件相关属性及方法 这一部分内容主要是将VB类模块的创建过程记录下: 1.打开VB,创建ActiveX DLL文件   2.修改工程名为...

Springboot+post请求接口

本文是Springboot+post请求接口的生成,包含了带cookie 和参数发送post请求。新增lombok框架,lombok的使用可以不用在类中添加成员变量的get/set方法。框架自带了相关方法。如不需要再添加以下内容 public String getUsename() { return usename; } p...

TypeScript躬行记(8)——装饰器

  装饰器(Decorator)可声明在类及其成员(例如属性、方法等)之上,为它们提供一种标注,用于分离复杂逻辑或附加额外逻辑,其语法形式为@expression。expression是一个会在运行时被调用的函数,它的参数是被装饰的声明信息。假设有一个@sealed装饰器,那么可以像下面这样定义sealed()函数。 function sealed(tar...

Java命令学习系列(三)——Jmap

jmap是JDK自带的工具软件,主要用于打印指定Java进程(或核心文件、远程调试服务器)的共享对象内存映射或堆内存细节。可以使用jmap生成Heap Dump。在Java命令学习系列(零)——常见命令及Java Dump介绍和Java命令学习系列(二)——Jstack中分别有关于Java Dump以及线程 Dump的介绍。这篇文章主要介绍Java的堆Du...

淘宝网Open API 入门教程

淘宝网Open API 入门教程 淘宝网的Open API开放将近一年了,越来越多的人(包括已工作的和在校的大学生)都在使用淘宝的Open API,有不少ISV应用已上架盈利了。我也使用淘宝的Open Api也大半年了。不过了,由于阿里软件的文档比较的乱,让很多初学者分不清头绪(注:淘宝网的Open API是开放在阿里软件的一个平台上,是什么服务集群平台吧...

对C#委托和事件委托的理解

委托的声明 public delegate void MyDelegate(string str);注1.委托的定义和方法的定义类似,只是在前面加了一个delegate,但委托不是方法,它是一种类型。是一种特殊的类型,看成是一种新的对象类型比较好理解。用于对与该委托有相 同签名的方法调用。2.委托相当于C++中的函数指针,但它是类型安全的。3.委托是从...