一、案例背景
A公司想要生产一款万能遥控器:使用本公司遥控器,只需要设置好需要被控制的设备,比如电视,空调,电灯等,便可以实现遥控,从此摆脱找不到遥控器的情况!
其他电器类的代码和实现已经相应的电器公司提供,你的任务是将这些代码融合进遥控器中,以实现遥控器的功能。
二、案例分析
听起来很不错的一个主意,但是怎么实现呢?
看过了那么多的设计模式,我想"针对接口编程,而不是针对实现编程"这条设计原则已经给你留下了些许印象。你可以会说:我们可以设计一个抽象电器接口,让其他电器类继承自这个接口,然后在遥控器类中使用组合,应该就可以解决问题。是的,但是你忽略了一个问题,电器类的代码已经由各大厂商给出,我们并不能随意修改这些代码。
这种情形下,命令模式也许能解决你的问题。该模式可以使"发出命令"和"执行命令"解耦,发出命令的人只管发出命令而不必关注执行者是怎么完成命令的。想像以下你走进一家餐厅的时候,是不是也只需要看着菜单点菜(下发命令)就行了,而后厨的王牌厨师们也根本不需要关注是谁点了这道西红柿炒蛋,你们不也是已经实现解耦了吗?
三、代码案例
cpp
#include <iostream>
#include <string>
#include <vector>
#include <array>
using namespace std;
class Command
{
public:
virtual void execute() const = 0;
};
class Light
{
public:
void on() const
{
cout << "灯开了..." << endl;
}
void off() const
{
cout << "灯关了..." << endl;
}
};
class TV
{
public:
void on() const
{
cout << "电视开了..." << endl;
}
void off() const
{
cout << "电视关了..." << endl;
}
};
class AC
{
public:
void on() const
{
cout << "空调开了..." << endl;
}
void off() const
{
cout << "空调关了..." << endl;
}
};
class LightOnCommand : public Command
{
private:
Light& light;
public:
LightOnCommand(Light& light) : light(light) {}
void execute() const override
{
light.on();
}
};
class LightOffCommand : public Command
{
private:
Light& light;
public:
LightOffCommand(Light& light) : light(light) {}
void execute() const override
{
light.off();
}
};
class TVOnCommand : public Command
{
private:
TV& tv;
public:
TVOnCommand(TV& tv) : tv(tv) {}
void execute() const override
{
tv.on();
}
};
class TVOffCommand : public Command
{
private:
TV& tv;
public:
TVOffCommand(TV& tv) : tv(tv) {}
void execute() const override
{
tv.off();
}
};
class ACOnCommand : public Command
{
private:
AC& ac;
public:
ACOnCommand(AC& ac) : ac(ac) {}
void execute() const override
{
ac.on();
}
};
class ACOffCommand : public Command
{
private:
AC& ac;
public:
ACOffCommand(AC& ac) : ac(ac) {}
void execute() const override
{
ac.off();
}
};
class Remote
{
private:
const static int MAX_SLOT_SUM = 7;
array<Command*, MAX_SLOT_SUM> onCommand {};
array<Command*, MAX_SLOT_SUM> offCommand {};
void execute(const int slot, array<Command*, MAX_SLOT_SUM>& command)
{
if (slot < MAX_SLOT_SUM)
{
if (command[slot])
{
command[slot]->execute();
}
else
{
std::cout << "slot " << slot << " is empty" << std::endl;
}
}
}
public:
Remote() {}
void set(int slot, Command& on, Command& off)
{
if (slot < MAX_SLOT_SUM)
{
onCommand[slot] = &on;
offCommand[slot] = &off;
}
}
void pressOnButton(const int slot)
{
execute(slot, onCommand);
}
void pressOffButton(const int slot)
{
execute(slot, offCommand);
}
};
enum
{
_TV,
_Light,
_AC
};
int main()
{
Remote remote;
TV tv {};
TVOnCommand tvOnCommand(tv);
TVOffCommand tvOffCommand(tv);
remote.set(_TV, tvOnCommand, tvOffCommand);
Light light {};
LightOnCommand lightOnCommand(light);
LightOffCommand lightOffCommand(light);
remote.set(_Light, lightOnCommand, lightOffCommand);
AC ac {};
ACOnCommand acOnCommand(ac);
ACOffCommand acOffCommand(ac);
remote.set(_AC, acOnCommand, acOffCommand);
remote.pressOnButton(0);
remote.pressOnButton(1);
remote.pressOnButton(2);
cout << endl << endl;
remote.pressOffButton(0);
remote.pressOffButton(1);
remote.pressOffButton(2);
return 0;
}