C++ 命令模式
外观
命令模式(Command Pattern)是行为型设计模式的一种,它将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,支持请求的排队、记录、撤销和重做等操作。在C++中,命令模式常用于解耦调用者(Invoker)和执行者(Receiver),使系统更灵活、可扩展。
基本概念[编辑 | 编辑源代码]
命令模式的核心思想是将操作请求与实际执行分离。它包含以下主要角色:
- Command(命令接口):声明执行操作的接口。
- ConcreteCommand(具体命令):实现命令接口,绑定一个接收者(Receiver)和动作。
- Receiver(接收者):知道如何执行与请求相关的操作。
- Invoker(调用者):存储命令对象并在适当时机触发命令。
- Client(客户端):创建具体命令并设置其接收者。
类图表示[编辑 | 编辑源代码]
代码示例[编辑 | 编辑源代码]
以下是一个简单的C++实现,展示命令模式的基本结构:
#include <iostream>
#include <memory>
// 接收者类
class Light {
public:
void turnOn() {
std::cout << "Light is ON" << std::endl;
}
void turnOff() {
std::cout << "Light is OFF" << std::endl;
}
};
// 命令接口
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
};
// 具体命令:开灯
class TurnOnCommand : public Command {
Light& light;
public:
explicit TurnOnCommand(Light& l) : light(l) {}
void execute() override {
light.turnOn();
}
};
// 具体命令:关灯
class TurnOffCommand : public Command {
Light& light;
public:
explicit TurnOffCommand(Light& l) : light(l) {}
void execute() override {
light.turnOff();
}
};
// 调用者
class RemoteControl {
std::unique_ptr<Command> command;
public:
void setCommand(std::unique_ptr<Command> cmd) {
command = std::move(cmd);
}
void pressButton() {
if (command) {
command->execute();
}
}
};
int main() {
Light light;
RemoteControl remote;
// 设置开灯命令并执行
remote.setCommand(std::make_unique<TurnOnCommand>(light));
remote.pressButton(); // 输出: Light is ON
// 设置关灯命令并执行
remote.setCommand(std::make_unique<TurnOffCommand>(light));
remote.pressButton(); // 输出: Light is OFF
return 0;
}
输出[编辑 | 编辑源代码]
Light is ON Light is OFF
实际应用场景[编辑 | 编辑源代码]
命令模式在以下场景中特别有用:
1. GUI按钮操作:每个按钮绑定一个命令对象,点击时触发执行。 2. 事务系统:支持命令的撤销(Undo)和重做(Redo)。 3. 任务队列:将命令对象存入队列,异步执行。
案例:支持撤销的操作[编辑 | 编辑源代码]
扩展上述代码,增加撤销功能:
// 带撤销的命令接口
class UndoableCommand : public Command {
public:
virtual void undo() = 0;
};
// 具体命令:调整亮度
class DimLightCommand : public UndoableCommand {
Light& light;
int prevLevel;
public:
explicit DimLightCommand(Light& l) : light(l), prevLevel(0) {}
void execute() override {
prevLevel = 50; // 假设保存当前亮度
std::cout << "Dimming light to 50%" << std::endl;
}
void undo() override {
std::cout << "Restoring light to " << prevLevel << "%" << std::endl;
}
};
// 客户端使用
int main() {
Light light;
RemoteControl remote;
auto dimCommand = std::make_unique<DimLightCommand>(light);
remote.setCommand(std::move(dimCommand));
remote.pressButton(); // 输出: Dimming light to 50%
// 假设通过其他方式获取命令指针进行撤销
dynamic_cast<UndoableCommand*>(remote.getCommand())->undo(); // 输出: Restoring light to 0%
}
数学表示[编辑 | 编辑源代码]
命令模式可以形式化表示为:
优缺点[编辑 | 编辑源代码]
优点:
- 解耦调用者和接收者。
- 支持命令的排队、日志、撤销/重做。
- 易于扩展新命令。
缺点:
- 每个命令需要一个单独的类,可能增加代码量。
总结[编辑 | 编辑源代码]
命令模式是C++中实现行为参数化的强大工具,尤其适合需要支持撤销、事务或宏操作的场景。通过将请求封装为对象,它提供了更高的灵活性和可维护性。