C++ 设计模式之命令模式
简介
1、命令模式 (Command)是一种行为型设计模式,它将一个请求封装为一个对象,从而使您可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
2、命令模式 (Command)应用场景包括但不限于:
2.1、需要将请求调用者和请求接收者解耦时。
2.2、需要支持撤销(Undo)和重做(Redo)操作时。
2.3、当系统需要支持命令的排队执行和历史记录功能时。
2.4、当系统需要组合命令,形成宏命令时。
3、命令模式 (Command)的构成
3.1、命令接口
class Command
{
public:
virtual ~Command() {};
virtual void execute() = 0;
};
3.2、具体命令
class Light
{
public:
void on();
void off();
};
3.3、命令执行对象
class LightOnCommand : public Command
{
public:
LightOnCommand(Light& li);
void execute();
private:
Light& light;
};
4、命令模式 (Command)的优点
4.1、解耦:调用方(客户端)和接收方(接收器)之间没有直接关系,双方只通过命令对象进行通信,更易于维护和扩展。
4.2、扩展性:新增命令或者改变命令的实现不会影响现有的其他类,符合开闭原则。
4.3、组合命令:可以将多个简单命令组合成一个复合命令(宏命令),方便执行多个操作。
4.4、支持撤销/重做:命令通常可以做到“可撤销”,容易实现操作的撤销和重做。
4.5、更好的控制:可以对命令进行排队和记录,以及在无需知道命令具体实现的情况下进行其他操作。
5、命令模式 (Command)的缺点
5.1、类膨胀:每个单独的命令都需要一个新的类进行包装,当命令多时类的数量会急剧增加。
5.2、复杂度增加:设计和实现更加复杂,特别是需要维护历史状态和相关状态回滚时。
简单示例
1、定义
// 命令接口
class Command
{
public:
virtual ~Command() {};
virtual void execute() = 0;
};
// 具体命令
class Light
{
public:
void on();
void off();
};
class LightOnCommand : public Command
{
public:
LightOnCommand(Light& li);
void execute();
private:
Light& light;
};
class LightOffCommand : public Command
{
public:
LightOffCommand(Light& li);
void execute();
private:
Light& light;
};
// 调用者
class SimpleRemoteControl
{
public:
SimpleRemoteControl();
void setCommand(Command* commend);
void buttonWasPressed();
private:
Command* solt;
};
2、实现
void Light::on()
{
std::cout << "Light is on" << std::endl;
}
void Light::off()
{
std::cout << "Light is off" << std::endl;
}
LightOnCommand::LightOnCommand(Light& li) : light(li)
{
}
void LightOnCommand::execute()
{
light.on();
}
LightOffCommand::LightOffCommand(Light& li) : light(li)
{
}
void LightOffCommand::execute()
{
light.off();
}
SimpleRemoteControl::SimpleRemoteControl() : solt(nullptr)
{
}
void SimpleRemoteControl::setCommand(Command* commend)
{
solt = commend;
}
void SimpleRemoteControl::buttonWasPressed()
{
if (solt)
{
solt->execute();
}
}
3、调用
SimpleRemoteControl si;
Light li;
LightOnCommand lightOn(li);
LightOffCommand lightOff(li);
si.setCommand(&lightOn);
si.buttonWasPressed();
si.setCommand(&lightOff);
si.buttonWasPressed();