C++ 命令模式实现
外观
C++命令模式实现[编辑 | 编辑源代码]
命令模式(Command Pattern)是一种行为设计模式,它将请求或操作封装为独立的对象,从而使你可以参数化客户端与不同的请求、队列或日志请求,并支持可撤销的操作。在C++中,命令模式常用于实现回调机制、任务队列或撤销/重做功能。
介绍[编辑 | 编辑源代码]
命令模式的核心思想是将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化。这种模式的主要组成部分包括:
- 命令接口(Command):声明执行操作的接口。
- 具体命令(ConcreteCommand):实现命令接口,绑定接收者与动作。
- 接收者(Receiver):知道如何执行与请求相关的操作。
- 调用者(Invoker):触发命令对象执行请求。
- 客户端(Client):创建具体的命令对象并设置其接收者。
命令模式的主要优点包括:
- 解耦调用操作的对象与知道如何实现操作的对象。
- 支持撤销和重做操作。
- 支持将命令组合成复合命令(宏命令)。
代码示例[编辑 | 编辑源代码]
以下是一个简单的C++实现示例,展示如何使用命令模式控制电器的开关:
#include <iostream>
#include <memory>
#include <vector>
// 接收者类:电器
class ElectronicDevice {
public:
void turnOn() {
std::cout << "Device is ON" << std::endl;
}
void turnOff() {
std::cout << "Device is OFF" << std::endl;
}
};
// 命令接口
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
};
// 具体命令:打开电器
class TurnOnCommand : public Command {
ElectronicDevice& device;
public:
explicit TurnOnCommand(ElectronicDevice& dev) : device(dev) {}
void execute() override {
device.turnOn();
}
};
// 具体命令:关闭电器
class TurnOffCommand : public Command {
ElectronicDevice& device;
public:
explicit TurnOffCommand(ElectronicDevice& dev) : device(dev) {}
void execute() override {
device.turnOff();
}
};
// 调用者:遥控器
class RemoteControl {
std::vector<std::unique_ptr<Command>> commands;
public:
void addCommand(std::unique_ptr<Command> cmd) {
commands.push_back(std::move(cmd));
}
void pressButton(int index) {
if (index >= 0 && index < commands.size()) {
commands[index]->execute();
}
}
};
int main() {
ElectronicDevice tv;
RemoteControl remote;
// 设置命令
remote.addCommand(std::make_unique<TurnOnCommand>(tv));
remote.addCommand(std::make_unique<TurnOffCommand>(tv));
// 执行命令
remote.pressButton(0); // 输出: Device is ON
remote.pressButton(1); // 输出: Device is OFF
return 0;
}
输出[编辑 | 编辑源代码]
Device is ON Device is OFF
类图[编辑 | 编辑源代码]
以下是用mermaid绘制的命令模式类图:
实际应用场景[编辑 | 编辑源代码]
命令模式在以下场景中特别有用: 1. GUI按钮和菜单项:每个按钮点击或菜单选择可以绑定到不同的命令对象。 2. 事务系统:每个操作可以封装为命令,支持撤销和重做。 3. 任务调度:将任务封装为命令对象,放入队列中按顺序执行。 4. 宏录制:将多个命令组合成一个复合命令。
高级应用:支持撤销[编辑 | 编辑源代码]
扩展前面的例子,添加撤销功能:
// 扩展命令接口支持撤销
class UndoableCommand : public Command {
public:
virtual void undo() = 0;
};
// 具体命令:带撤销的开关命令
class ToggleCommand : public UndoableCommand {
ElectronicDevice& device;
bool wasOn = false;
public:
explicit ToggleCommand(ElectronicDevice& dev) : device(dev) {}
void execute() override {
wasOn = !wasOn;
if (wasOn) device.turnOn();
else device.turnOff();
}
void undo() override {
wasOn = !wasOn;
if (wasOn) device.turnOn();
else device.turnOff();
}
};
// 扩展调用者支持撤销
class AdvancedRemoteControl {
std::vector<std::unique_ptr<UndoableCommand>> commands;
std::vector<std::unique_ptr<UndoableCommand>> history;
public:
void addCommand(std::unique_ptr<UndoableCommand> cmd) {
commands.push_back(std::move(cmd));
}
void pressButton(int index) {
if (index >= 0 && index < commands.size()) {
commands[index]->execute();
history.push_back(std::move(commands[index]));
commands.erase(commands.begin() + index);
}
}
void undoLast() {
if (!history.empty()) {
history.back()->undo();
history.pop_back();
}
}
};
数学表示[编辑 | 编辑源代码]
命令模式可以形式化表示为:
总结[编辑 | 编辑源代码]
命令模式在C++中提供了一种灵活的方式来封装操作请求,使系统更易于扩展和维护。通过将请求封装为对象,你可以:
- 参数化对象与不同请求
- 支持队列请求
- 实现撤销/重做功能
- 构建复合命令(宏命令)
这种模式特别适合需要解耦发送者和接收者、或者需要支持事务性操作的场景。对于C++开发者来说,结合智能指针和现代C++特性可以创建更安全、更高效的命令模式实现。