在软件构建过程中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合——比如需要对行为进行“记录、撤销/重做(undo/redo)、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?
这种情况下就可以使用命令模式,命令模式即将一个请求(行为)封装为一个对象,从而使你可用不同的请求对客户端进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
UML图:
举个例子,当前智能家居很火热,假设我们要设计一个手机app,可以通过按动上边的控制按钮控制卧室和厨房的灯,还能控制卧室中的音响的开关。app即是“动作的请求者”,而灯和音响就是“动作的执行者”。当我们按动app上的某个开关后,app就可以把相关的指令发送到我们的指定的家电上。这之中app和家电之间是解耦的,我们完全可以通过设置,添加、修改或删除其它的家电控制功能,而不需要修改app的代码。
代码如下:
#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) {
m_sLocation = location;
}
void on() {
printf("%s light is on\n", m_sLocation.c_str());
}
void off() {
printf("%s light is off\n", m_sLocation.c_str());
}
private:
string m_sLocation;
};
class LightOffCommand : public Command
{
public:
LightOffCommand(string location) :m_Light(location) {}
void execute() {
m_Light.off();
}
private:
Light m_Light;
};
class LightOnCommand : public Command
{
public:
LightOnCommand(string location) :m_Light(location) {}
void execute() {
m_Light.on();
}
private:
Light m_Light;
};
class Stereo
{
public:
Stereo(string location) {
m_sLocation = location;
}
void on() {
printf("%s stereo is on\n", m_sLocation.c_str());
}
void off() {
printf("%s stereo is off\n", m_sLocation.c_str());
}
void setCD() {
printf("%s stereo is set for CD input\n", m_sLocation.c_str());
}
void setDVD() {
printf("%s stereo is set for DVD input\n", m_sLocation.c_str());
}
void setRadio() {
printf("%s stereo is set for Radio\n", m_sLocation.c_str());
}
void setVolume(int volume) {
printf("%s Stereo volume set to %d\n", m_sLocation.c_str(), volume);
}
private:
string m_sLocation;
};
class StereoOnWithCDCommand : public Command
{
public:
StereoOnWithCDCommand(string location) :m_Stereo(location) {}
void execute() {
m_Stereo.on();
m_Stereo.setCD();
m_Stereo.setVolume(11);
}
private:
Stereo m_Stereo;
};
class StereoOffCommand : public Command
{
public:
StereoOffCommand(string location) :m_Stereo(location) {}
void execute() {
m_Stereo.off();
}
private:
Stereo m_Stereo;
};
class RemoteControl
{
public:
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() {
for (int i = 0; i < 7; i++)
{
delete m_OnCommands.at(i);
delete m_OffCommands.at(i);
}
m_OnCommands.clear();
m_OffCommands.clear();
}
void 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 onButtonWasPushed(int slot) {
m_OnCommands.at(slot)->execute();
}
void offButtonWasPushed(int slot) {
m_OffCommands.at(slot)->execute();
}
private:
vector<Command*> m_OnCommands;
vector<Command*> m_OffCommands;
};
int main()
{
RemoteControl remoteControl;
LightOffCommand* pLivingRoomLightOff = new LightOffCommand("卧室");
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
推荐阅读:精品时尚网
-
设计模式19-Command(命令)模式-智
在软件构建过程中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合——比如需要对行为进行“记录、撤销/重做(undo/redo)、事务”等处理...
2020-08-13 -
海康、美的拟分拆智能家居板块独立上市,剑指千
文/杨剑勇家庭智能化规模日益普及,倘若新购买电视、冰箱等家电,几乎都已成智能化设备,特别是智能音箱已成智能家居场景标配智能硬件,作为中枢级智能硬件,智能音箱是家...
2020-08-13 -
精彩!韩国电影创造历史,黑寡妇斯嘉丽入行25
就在刚刚,第92届奥斯卡金像奖公布了提名名单,《小丑》获11项提名领跑,《爱尔兰人》、《1917》和《好莱坞往事》获得10提紧随其后,《乔乔的异想世界》《婚姻故...
2020-01-14 -
IU粉丝太会玩!把演唱会秒变恐怖现场,堪称年
韩国歌手IU李知恩是圈里出了名的宠粉狂魔了。前不久,IU为了演唱会前往印尼雅加达,在机场认出了自己的粉丝,经询问原来对方要去看她的演唱会。之后,IU邀请该名粉丝...
2020-01-14 -
不煽情,不撕逼,太久没看到这么令人舒适的节目
我终于知道,原来旅行类节目可以好好拍!原来和完全不同性格或不相熟的人旅游,真的可以是一件舒心的事儿。没有恶意剪辑、没有刻意撕逼,甚至没有什么特别设计的笑点哭点。...
2020-01-14 -
身高欠费的小个子不要怕,推荐你杨丞琳3套穿搭
被称为可爱教主的杨丞琳出演过很多台湾偶像剧,之后也发表过很多脍炙人口的歌曲,这些都是许多80后90后的青春回忆。现已经35岁的她依然保持着年轻的心态,平日的穿搭...
2020-01-14 -
谭松韵29岁了还这么显嫩!穿墨绿色针织上衣戴
最近谭松韵和任嘉伦的《锦衣之下》真是让人上头啊,两位主演的年纪其实都已经不小了,但演起来依旧毫无违和感,特别是谭松韵,不管和比自己小多少的男演员搭戏都少女感十足...
2020-01-14 -
《王牌对王牌》新一季官宣了,第一期就放大招,
不同的季节每个台都会著作不同的综艺节目,而现在正值春节,每个卫视也都该出春节期间的综艺节目了,例如湖南卫视的《歌手》,据报道《歌手》已经在录制中了,华晨宇、毛不...
2020-01-14