23种设计模式 - 命令模式
模式定义
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装为独立对象,使请求的发送者与接收者解耦。通过将操作抽象为命令对象,支持命令的存储、传递、撤销和重做,增强系统的灵活性和可扩展性。
模式结构
抽象命令类(Command)
- 定义执行命令的统一接口(如
execute()
方法),声明撤销/重做等扩展功能。
具体命令类(ConcreteCommand) - 实现抽象命令接口,关联接收者对象并调用其具体方法(如启动、暂停数控机床)。
接收者(Receiver) - 实际执行操作的对象(如数控机床),包含具体的业务逻辑。
调用者(Invoker) - 持有命令对象并触发其执行(如数控系统控制面板)。
客户端(Client) - 创建命令对象并配置其接收者。
适用场景
操作队列化:如数控系统需要支持批量执行加工指令。
撤销/重做功能:支持机床操作的历史记录回滚。
分布式通信:将远程控制指令封装为可传输对象。
C++示例(数控系统场景)
场景说明:
数控机床通过控制面板发送命令(启动、暂停、急停),命令被封装为对象,支持操作记录和撤销。
#include
#include
#include
// 接收者:数控机床
class CNC_Machine {
public:
void start() {
std::cout << "数控机床启动,开始加工..." << std::endl;
}
void pause() {
std::cout << "数控机床暂停..." << std::endl;
}
void emergencyStop() {
std::cout << "紧急停止!机床复位中..." << std::endl;
}
};
// 抽象命令类
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
virtual void undo() = 0; // 支持撤销操作[4][7]
};
// 具体命令:启动命令
class StartCommand : public Command {
private:
CNC_Machine& receiver_;
public:
explicit StartCommand(CNC_Machine& machine) : receiver_(machine) {}
void execute() override {
receiver_.start();
}
void undo() override {
std::cout << "撤销启动:停止加工" << std::endl;
}
};
// 具体命令:急停命令
class EmergencyStopCommand : public Command {
private:
CNC_Machine& receiver_;
public:
explicit EmergencyStopCommand(CNC_Machine& machine) : receiver_(machine) {}
void execute() override {
receiver_.emergencyStop();
}
void undo() override {
std::cout << "撤销急停:恢复运行状态" << std::endl;
}
};
// 调用者:控制面板
class ControlPanel {
private:
std::stack> history_;
public:
void executeCommand(std::unique_ptr cmd) {
cmd->execute();
history_.push(std::move(cmd)); // 记录操作历史[4][7]
}
void undoLastCommand() {
if (!history_.empty()) {
history_.top()->undo();
history_.pop();
}
}
};
// 客户端使用
int main() {
CNC_Machine machine;
ControlPanel panel;
// 发送启动命令
panel.executeCommand(std::make_unique(machine));
// 发送急停命令
panel.executeCommand(std::make_unique(machine));
// 撤销上一次操作
panel.undoLastCommand(); // 输出:撤销急停:恢复运行状态
return 0;
}
代码解析
接收者:CNC_Machine
类实现机床的实际操作(如启动、急停)。
具体命令:StartCommand
和EmergencyStopCommand
封装操作,关联接收者对象。
调用者:ControlPanel
管理命令执行历史,支持撤销操作。
解耦优势:新增命令(如暂停命令)只需扩展Command
子类,无需修改调用者代码。