命令模式(Command Pattern)是一种行为设计模式,它将请求封装为对象,从而使你可以参数化客户端使用不同的请求、队列或日志请求,以及支持可撤销的操作。
核心概念
设计原则
命令模式遵循以下设计原则:
单一职责原则:将调用操作的对象与执行操作的对象分离
开闭原则:可以引入新命令而不修改现有代码
松耦合:解耦请求发送者和接收者
主要优点
解耦:分离请求的发送者和接收者
可扩展:容易添加新命令
可组合:可以组合多个命令
支持撤销:可以实现命令的撤销和重做
延迟执行:支持命令的队列和延迟执行
模式结构
主要组件
Command(命令接口)
声明执行操作的接口
ConcreteCommand(具体命令)
实现命令接口
定义接收者与动作之间的绑定关系
调用接收者的操作
Invoker(调用者)
要求命令执行请求
Receiver(接收者)
知道如何执行与请求相关的操作
Client(客户端)
创建具体命令并设置接收者
完整代码示例
#include <iostream>
#include <memory>
#include <vector>
#include <stack>
#include <string>
// ==================== 接收者类 ====================
// 电灯 - 接收者1
class Light {
std::string location_;
public:
explicit Light(const std::string& location) : location_(location) {}
void on() {
std::cout << location_ << " 电灯打开" << std::endl;
}
void off() {
std::cout << location_ << " 电灯关闭" << std::endl;
}
};
// 风扇 - 接收者2
class Fan {
enum { OFF, LOW, MEDIUM, HIGH } speed_;
public:
Fan() : speed_(OFF) {}
void low() {
speed_ = LOW;
std::cout << "风扇设置为低速" << std::endl;
}
void medium() {
speed_ = MEDIUM;
std::cout << "风扇设置为中速" << std::endl;
}
void high() {
speed_ = HIGH;
std::cout << "风扇设置为高速" << std::endl;
}
void off() {
speed_ = OFF;
std::cout << "风扇关闭" << std::endl;
}
int getSpeed() const {
return speed_;
}
};
// ==================== 命令接口 ====================
class Command {
public:
virtual void execute() = 0;
virtual void undo() = 0;
virtual ~Command() = default;
};
// ==================== 具体命令 ====================
// 电灯开命令
class LightOnCommand : public Command {
Light& light_;
public:
explicit LightOnCommand(Light& light) : light_(light) {}
void execute() override {
light_.on();
}
void undo() override {
light_.off();
}
};
// 电灯关命令
class LightOffCommand : public Command {
Light& light_;
public:
explicit LightOffCommand(Light& light) : light_(light) {}
void execute() override {
light_.off();
}
void undo() override {
light_.on();
}
};
// 风扇命令基类
class FanCommand : public Command {
protected:
Fan& fan_;
int prevSpeed_;
public:
explicit FanCommand(Fan& fan) : fan_(fan), prevSpeed_(fan.getSpeed()) {}
void undo() override {
switch (prevSpeed_) {
case Fan::HIGH: fan_.high(); break;
case Fan::MEDIUM: fan_.medium(); break;
case Fan::LOW: fan_.low(); break;
default: fan_.off(); break;
}
}
};
// 风扇高速命令
class FanHighCommand : public FanCommand {
public:
explicit FanHighCommand(Fan& fan) : FanCommand(fan) {}
void execute() override {
prevSpeed_ = fan_.getSpeed();
fan_.high();
}
};
// 风扇关闭命令
class FanOffCommand : public FanCommand {
public:
explicit FanOffCommand(Fan& fan) : FanCommand(fan) {}
void execute() override {
prevSpeed_ = fan_.getSpeed();
fan_.off();
}
};
// 宏命令 - 命令组合
class MacroCommand : public Command {
std::vector<std::unique_ptr<Command>> commands_;
public:
void addCommand(std::unique_ptr<Command> cmd) {
commands_.push_back(std::move(cmd));
}
void execute() override {
for (const auto& cmd : commands_) {
cmd->execute();
}
}
void undo() override {
// 反向执行undo
for (auto it = commands_.rbegin(); it != commands_.rend(); ++it) {
(*it)->undo();
}
}
};
// ==================== 调用者 ====================
class RemoteControl {
std::vector<std::unique_ptr<Command>> onCommands_;
std::vector<std::unique_ptr<Command>> offCommands_;
std::stack<std::unique_ptr<Command>> undoStack_;
public:
RemoteControl() {
// 初始化空命令
auto noCommand = std::make_unique<Command>();
for (int i = 0; i < 7; i++) {
onCommands_.push_back(std::make_unique<NoCommand>());
offCommands_.push_back(std::make_unique<NoCommand>());
}
}
void setCommand(int slot, std::unique_ptr<Command> onCmd, std::unique_ptr<Command> offCmd) {
onCommands_[slot] = std::move(onCmd);
offCommands_[slot] = std::move(offCmd);
}
void onButtonWasPushed(int slot) {
if (onCommands_[slot]) {
onCommands_[slot]->execute();
undoStack_.push(onCommands_[slot]->clone()); // 假设Command实现了clone方法
}
}
void offButtonWasPushed(int slot) {
if (offCommands_[slot]) {
offCommands_[slot]->execute();
undoStack_.push(offCommands_[slot]->clone());
}
}
void undoButtonWasPushed() {
if (!undoStack_.empty()) {
undoStack_.top()->undo();
undoStack_.pop();
}
}
// 空命令类
class NoCommand : public Command {
public:
void execute() override {}
void undo() override {}
};
};
// ==================== 客户端代码 ====================
int main() {
std::cout << "=== 命令模式演示: 智能家居遥控器 ===" << std::endl;
// 创建接收者
Light livingRoomLight("客厅");
Light kitchenLight("厨房");
Fan ceilingFan;
// 创建命令
auto livingRoomLightOn = std::make_unique<LightOnCommand>(livingRoomLight);
auto livingRoomLightOff = std::make_unique<LightOffCommand>(livingRoomLight);
auto kitchenLightOn = std::make_unique<LightOnCommand>(kitchenLight);
auto kitchenLightOff = std::make_unique<LightOffCommand>(kitchenLight);
auto ceilingFanHigh = std::make_unique<FanHighCommand>(ceilingFan);
auto ceilingFanOff = std::make_unique<FanOffCommand>(ceilingFan);
// 创建宏命令
auto partyOn = std::make_unique<MacroCommand>();
dynamic_cast<MacroCommand*>(partyOn.get())->addCommand(std::move(livingRoomLightOn));
dynamic_cast<MacroCommand*>(partyOn.get())->addCommand(std::move(kitchenLightOn));
dynamic_cast<MacroCommand*>(partyOn.get())->addCommand(std::move(ceilingFanHigh));
auto partyOff = std::make_unique<MacroCommand>();
dynamic_cast<MacroCommand*>(partyOff.get())->addCommand(std::move(livingRoomLightOff));
dynamic_cast<MacroCommand*>(partyOff.get())->addCommand(std::move(kitchenLightOff));
dynamic_cast<MacroCommand*>(partyOff.get())->addCommand(std::move(ceilingFanOff));
// 设置遥控器
RemoteControl remote;
remote.setCommand(0, std::make_unique<LightOnCommand>(livingRoomLight),
std::make_unique<LightOffCommand>(livingRoomLight));
remote.setCommand(1, std::make_unique<LightOnCommand>(kitchenLight),
std::make_unique<LightOffCommand>(kitchenLight));
remote.setCommand(2, std::make_unique<FanHighCommand>(ceilingFan),
std::make_unique<FanOffCommand>(ceilingFan));
remote.setCommand(3, std::move(partyOn), std::move(partyOff));
// 测试遥控器
std::cout << "\n--- 测试单个命令 ---" << std::endl;
remote.onButtonWasPushed(0); // 打开客厅灯
remote.offButtonWasPushed(0); // 关闭客厅灯
remote.undoButtonWasPushed(); // 撤销
std::cout << "\n--- 测试风扇命令 ---" << std::endl;
remote.onButtonWasPushed(2); // 风扇高速
remote.offButtonWasPushed(2); // 风扇关闭
remote.undoButtonWasPushed(); // 撤销
std::cout << "\n--- 测试宏命令 ---" << std::endl;
remote.onButtonWasPushed(3); // 派对模式开
remote.offButtonWasPushed(3); // 派对模式关
remote.undoButtonWasPushed(); // 撤销
return 0;
}
模式变体
1. 支持重做的命令模式
class CommandHistory {
std::stack<std::unique_ptr<Command>> undoStack_;
std::stack<std::unique_ptr<Command>> redoStack_;
public:
void execute(std::unique_ptr<Command> cmd) {
cmd->execute();
undoStack_.push(std::move(cmd));
// 执行新命令时清空重做栈
while (!redoStack_.empty()) redoStack_.pop();
}
void undo() {
if (!undoStack_.empty()) {
auto cmd = std::move(undoStack_.top());
undoStack_.pop();
cmd->undo();
redoStack_.push(std::move(cmd));
}
}
void redo() {
if (!redoStack_.empty()) {
auto cmd = std::move(redoStack_.top());
redoStack_.pop();
cmd->execute();
undoStack_.push(std::move(cmd));
}
}
};
2. 事务性命令
class TransactionalCommand : public Command {
std::vector<std::unique_ptr<Command>> commands_;
bool executed_ = false;
public:
void addCommand(std::unique_ptr<Command> cmd) {
if (!executed_) {
commands_.push_back(std::move(cmd));
}
}
void execute() override {
if (!executed_) {
for (const auto& cmd : commands_) {
cmd->execute();
}
executed_ = true;
}
}
void undo() override {
if (executed_) {
for (auto it = commands_.rbegin(); it != commands_.rend(); ++it) {
(*it)->undo();
}
executed_ = false;
}
}
};
实际应用场景
GUI操作:菜单项、按钮点击等操作的封装
事务系统:支持原子操作和回滚
游戏开发:游戏命令、回放系统
智能家居:设备控制命令
任务队列:异步任务执行和调度