当前位置: 首页 > news >正文

命令模式C++

命令模式(Command Pattern)是一种行为型设计模式,它将请求封装为一个对象,使你可以用不同的请求对客户进行参数化,还能支持请求的排队、记录日志及撤销操作。这种模式将发送者和接收者解耦,发送者无需知道接收者的具体实现。

命令模式的核心角色

  1. Command(命令接口):声明执行操作的接口(通常是execute()方法)
  2. ConcreteCommand(具体命令):实现命令接口,绑定接收者和具体操作
  3. Receiver(接收者):执行命令所对应的操作,知道如何实施具体行为
  4. Invoker(调用者):要求命令执行请求,持有命令对象
  5. Client(客户端):创建具体命令对象并设置其接收者

C++实现示例

以下以"智能家居控制系统"为例实现命令模式,支持对灯光、电视等设备的操作,以及命令的撤销功能:

#include <iostream>
#include <string>
#include <vector>
#include <memory>// 前向声明接收者类
class Light;
class Television;// 命令接口
class Command {
public:virtual ~Command() = default;virtual void execute() = 0;virtual void undo() = 0;virtual std::string getName() const = 0;
};// 接收者1:灯光
class Light {
private:std::string location;bool isOn;public:Light(std::string loc) : location(std::move(loc)), isOn(false) {}void on() {isOn = true;std::cout << location << "灯光 打开" << std::endl;}void off() {isOn = false;std::cout << location << "灯光 关闭" << std::endl;}bool getState() const {return isOn;}
};// 接收者2:电视
class Television {
private:std::string location;bool isOn;int channel;int volume;public:Television(std::string loc) : location(std::move(loc)), isOn(false), channel(1), volume(5) {}void on() {isOn = true;std::cout << location << "电视 打开" << std::endl;}void off() {isOn = false;std::cout << location << "电视 关闭" << std::endl;}void setChannel(int ch) {channel = ch;std::cout << location << "电视 频道设置为: " << channel << std::endl;}void setVolume(int vol) {volume = vol;std::cout << location << "电视 音量设置为: " << volume << std::endl;}bool getState() const {return isOn;}int getChannel() const {return channel;}int getVolume() const {return volume;}
};// 具体命令1:开灯
class LightOnCommand : public Command {
private:Light* light;bool previousState;  // 用于撤销操作public:LightOnCommand(Light* l) : light(l) {}void execute() override {previousState = light->getState();light->on();}void undo() override {if (previousState) {light->on();} else {light->off();}std::cout << "撤销 " << getName() << std::endl;}std::string getName() const override {return light->getState() ? "开灯" : "关灯";}
};// 具体命令2:关灯
class LightOffCommand : public Command {
private:Light* light;bool previousState;public:LightOffCommand(Light* l) : light(l) {}void execute() override {previousState = light->getState();light->off();}void undo() override {if (previousState) {light->on();} else {light->off();}std::cout << "撤销 " << getName() << std::endl;}std::string getName() const override {return "关灯";}
};// 具体命令3:开电视
class TvOnCommand : public Command {
private:Television* tv;bool previousState;int previousChannel;int previousVolume;public:TvOnCommand(Television* t) : tv(t) {}void execute() override {previousState = tv->getState();previousChannel = tv->getChannel();previousVolume = tv->getVolume();tv->on();tv->setChannel(5);  // 默认打开5频道tv->setVolume(7);   // 默认音量7}void undo() override {if (previousState) {tv->on();tv->setChannel(previousChannel);tv->setVolume(previousVolume);} else {tv->off();}std::cout << "撤销 " << getName() << std::endl;}std::string getName() const override {return "开电视";}
};// 具体命令4:关电视
class TvOffCommand : public Command {
private:Television* tv;bool previousState;public:TvOffCommand(Television* t) : tv(t) {}void execute() override {previousState = tv->getState();tv->off();}void undo() override {if (previousState) {tv->on();} else {tv->off();}std::cout << "撤销 " << getName() << std::endl;}std::string getName() const override {return "关电视";}
};// 调用者:遥控器
class RemoteControl {
private:std::vector<std::unique_ptr<Command>> onCommands;std::vector<std::unique_ptr<Command>> offCommands;std::unique_ptr<Command> undoCommand;  // 记录上一个命令用于撤销public:RemoteControl(int slotCount) {// 初始化命令槽位onCommands.resize(slotCount);offCommands.resize(slotCount);}// 设置命令void setCommand(int slot, std::unique_ptr<Command> onCmd, std::unique_ptr<Command> offCmd) {if (slot >= 0 && slot < onCommands.size()) {onCommands[slot] = std::move(onCmd);offCommands[slot] = std::move(offCmd);}}// 按下开按钮void pressOnButton(int slot) {if (slot >= 0 && slot < onCommands.size() && onCommands[slot]) {onCommands[slot]->execute();undoCommand = std::move(onCommands[slot]);  // 保存命令用于撤销}}// 按下关按钮void pressOffButton(int slot) {if (slot >= 0 && slot < offCommands.size() && offCommands[slot]) {offCommands[slot]->execute();undoCommand = std::move(offCommands[slot]);  // 保存命令用于撤销}}// 按下撤销按钮void pressUndoButton() {if (undoCommand) {undoCommand->undo();} else {std::cout << "没有可撤销的操作" << std::endl;}}
};// 客户端代码
int main() {// 创建接收者Light* livingRoomLight = new Light("客厅");Light* bedroomLight = new Light("卧室");Television* livingRoomTv = new Television("客厅");// 创建命令auto livingRoomLightOn = std::make_unique<LightOnCommand>(livingRoomLight);auto livingRoomLightOff = std::make_unique<LightOffCommand>(livingRoomLight);auto bedroomLightOn = std::make_unique<LightOnCommand>(bedroomLight);auto bedroomLightOff = std::make_unique<LightOffCommand>(bedroomLight);auto tvOn = std::make_unique<TvOnCommand>(livingRoomTv);auto tvOff = std::make_unique<TvOffCommand>(livingRoomTv);// 创建遥控器(调用者),有3个槽位RemoteControl remote(3);// 给遥控器设置命令remote.setCommand(0, std::move(livingRoomLightOn), std::move(livingRoomLightOff));remote.setCommand(1, std::move(bedroomLightOn), std::move(bedroomLightOff));remote.setCommand(2, std::move(tvOn), std::move(tvOff));// 测试操作std::cout << "=== 执行一系列操作 ===" << std::endl;remote.pressOnButton(0);   // 开客厅灯remote.pressOnButton(2);   // 开客厅电视remote.pressOffButton(0);  // 关客厅灯remote.pressOnButton(1);   // 开卧室灯// 测试撤销std::cout << "\n=== 测试撤销操作 ===" << std::endl;remote.pressUndoButton();  // 撤销"开卧室灯"remote.pressUndoButton();  // 撤销"关客厅灯"remote.pressUndoButton();  // 撤销"开客厅电视"// 清理资源delete livingRoomLight;delete bedroomLight;delete livingRoomTv;return 0;
}

代码解析

  1. 命令接口(Command:定义了execute()(执行命令)和undo()(撤销命令)方法,所有具体命令都需实现这两个方法。

  2. 接收者(LightTelevision:实现具体的业务逻辑(如开灯、关灯、开电视等),命令对象会调用这些方法。

  3. 具体命令

    • 每个命令类绑定一个接收者和对应的操作(如LightOnCommand绑定Lighton()方法)
    • 实现execute()方法调用接收者的相应操作,并保存执行前的状态用于undo()
  4. 调用者(RemoteControl

    • 持有多个命令对象(开/关命令对),通过按钮触发命令执行
    • 记录上一个执行的命令,支持undo()操作
  5. 工作流程:客户端创建命令并绑定接收者,调用者通过命令间接操作接收者,实现了发送者与接收者的解耦。

命令模式的优缺点

优点

  • 实现了发送者与接收者的解耦,发送者无需知道接收者的具体实现
  • 容易扩展新命令,符合开放-封闭原则
  • 支持命令的排队、日志记录和撤销操作
  • 可以组合多个命令形成复合命令(宏命令)

缺点

  • 可能导致系统中出现大量具体命令类,增加系统复杂度
  • 命令的撤销/重做功能实现复杂,需要保存历史状态

适用场景

  • 当需要将请求发送者与接收者解耦时
  • 当需要支持命令的撤销、重做操作时
  • 当需要将多个命令组合成复合命令时
  • 当需要实现请求的排队执行或日志记录时

常见应用:

  • 图形界面中的菜单操作、按钮点击
  • 事务处理(支持提交和回滚)
  • 任务调度系统(命令排队执行)
  • 遥控器、游戏手柄等设备的操作抽象

命令模式通过将操作封装为对象,为系统带来了更大的灵活性和可扩展性,特别适合需要支持撤销、日志、事务等功能的场景。

http://www.lryc.cn/news/622380.html

相关文章:

  • 【DSP28335 事件驱动】唤醒沉睡的 CPU:外部中断 (XINT) 实战
  • AI - MCP 协议(一)
  • 备忘录模式C++
  • 线性代数 · 直观理解矩阵 | 空间变换 / 特征值 / 特征向量
  • JavaScript递归
  • nVidia Tesla P40使用anaconda本地重编译pytorch3d成功加载ComfyUI-3D-Pack
  • 磁悬浮轴承“幽灵振动”克星:深度解析同频振动机理与精准打击策略
  • 日常反思总结
  • Layui 语法详解与全功能示例
  • GoLand深度解析:智能开发利器与cpolar内网穿透的协同革命
  • 基于Spring Boot的智能民宿预订与游玩系统设计与实现 民宿管理系统 民宿预订系统 民宿订房系统
  • Linux操作系统从入门到实战(二十二)命令行参数与环境变量
  • Lecture 10: Concurrency 3
  • 【嵌入式硬件实例】-555定时器驱动直流无刷电机
  • kubernetes(序)
  • ESP32-C3_TCP
  • Windows Server存储智能数据校验
  • Spring Boot接口签名校验设计与实现
  • 办公效率提升指南:完成重复任务自动化
  • Docker Compose 入门教程
  • 图片滤镜处理(filters)
  • lidar2imu/auto_caliban以及manual_calib安装过程
  • 线程P5 | 单例模式[线程安全版]~懒汉 + 饿汉
  • 【C#补全计划】委托
  • Vue 侦听器(watch 与 watchEffect)全解析2
  • SSH协议的GIT转换
  • pyecharts可视化图表-pie:从入门到精通(进阶篇)
  • 集成电路学习:什么是Image Segmentation图像分割
  • GPT-5 官方前瞻:它将如何重塑你的数字生活?
  • 艾伦·图灵:计算理论与人工智能的奠基人