首页 > 后端开发 > C++ > 正文

C++如何实现命令模式 C++命令模式的设计与示例

冰火之心
发布: 2025-06-26 12:16:01
原创
461人浏览过

命令模式封装请求以解耦发送者与接收者,策略模式封装算法以实现运行时替换。命令模式的核心在于将请求封装为对象,使能支持撤销、日志、排队等功能,主要涉及command、concretecommand、receiver、invoker和client五个角色;而策略模式通过封装不同的算法族,允许算法独立变化并可在运行时切换,核心在于算法的可替换性。两者虽均基于接口设计思想,但应用场景不同:命令模式适用于gui操作、事务处理、游戏动作记录等需保存或撤销请求的场景,策略模式则适用于支付方式、排序算法等需动态切换行为的场景。

C++如何实现命令模式 C++命令模式的设计与示例

C++命令模式的核心在于将请求封装成一个对象,从而允许你参数化客户端对象,支持请求排队、记录请求日志,以及支持可撤销的操作。简单来说,就是把“做什么”和“谁去做”解耦。

C++如何实现命令模式 C++命令模式的设计与示例

解决方案

C++如何实现命令模式 C++命令模式的设计与示例

命令模式涉及几个关键角色:

立即学习C++免费学习笔记(深入)”;

C++如何实现命令模式 C++命令模式的设计与示例
  • Command(命令接口): 声明执行操作的接口。
  • ConcreteCommand(具体命令): 将一个接收者对象绑定于一个动作。调用接收者相应的操作,以实现 Execute。
  • Receiver(接收者): 知道如何实施与执行一个请求相关的操作。任何类都可以作为接收者。
  • Invoker(调用者): 要求命令执行请求。
  • Client(客户端): 创建 ConcreteCommand 对象并设置其接收者。

以下是一个简单的C++命令模式示例:

#include <iostream>
#include <vector>

// Receiver
class Light {
public:
    void turnOn() {
        std::cout << "Light is ON" << std::endl;
    }

    void turnOff() {
        std::cout << "Light is OFF" << std::endl;
    }
};

// Command Interface
class Command {
public:
    virtual void execute() = 0;
    virtual ~Command() {}
};

// Concrete Command
class TurnOnCommand : public Command {
private:
    Light* light;

public:
    TurnOnCommand(Light* light) : light(light) {}

    void execute() override {
        light->turnOn();
    }
};

// Concrete Command
class TurnOffCommand : public Command {
private:
    Light* light;

public:
    TurnOffCommand(Light* light) : light(light) {}

    void execute() override {
        light->turnOff();
    }
};

// Invoker
class RemoteControl {
private:
    std::vector<Command*> commands;

public:
    void setCommand(Command* command) {
        commands.push_back(command);
    }

    void pressButton() {
        if (!commands.empty()) {
            commands.back()->execute();
            commands.pop_back(); // 执行后移除,简化示例
        } else {
            std::cout << "No command set" << std::endl;
        }
    }
};

int main() {
    Light* livingRoomLight = new Light();

    TurnOnCommand* turnOnCmd = new TurnOnCommand(livingRoomLight);
    TurnOffCommand* turnOffCmd = new TurnOffCommand(livingRoomLight);

    RemoteControl* remote = new RemoteControl();
    remote->setCommand(turnOnCmd);
    remote->setCommand(turnOffCmd);

    remote->pressButton(); // Light is OFF (因为后设置的是TurnOffCommand)
    remote->pressButton(); // Light is ON

    delete turnOnCmd;
    delete turnOffCmd;
    delete livingRoomLight;
    delete remote;

    return 0;
}
登录后复制

这个例子中,Light是接收者,TurnOnCommand和TurnOffCommand是具体命令,RemoteControl是调用者。 客户端负责创建命令并将它们传递给调用者。

命令模式在C++中有什么实际应用场景?

命令模式在GUI应用程序、事务处理、宏记录、以及游戏开发中都有广泛应用。例如,在文本编辑器中,每个操作(如复制、粘贴、删除)都可以封装成一个命令对象。这样做的好处是,可以很容易地实现撤销/重做功能,只需要维护一个命令历史记录即可。此外,命令模式还可以用于实现复杂的事务处理,确保一系列操作要么全部成功执行,要么全部回滚。 在游戏开发中,玩家的每一个操作(如移动、攻击)都可以视为一个命令,便于记录和回放。

C++中如何实现命令的撤销(Undo)和重做(Redo)?

实现撤销和重做功能,需要在Command接口中添加undo()方法,并在ConcreteCommand中实现该方法。同时,需要维护一个命令历史栈,用于记录已执行的命令。

// Command Interface (with Undo)
class Command {
public:
    virtual void execute() = 0;
    virtual void undo() = 0; // 添加 undo 方法
    virtual ~Command() {}
};

// Concrete Command (with Undo)
class TurnOnCommand : public Command {
private:
    Light* light;
    bool previousState; // 记录之前的状态,以便 undo

public:
    TurnOnCommand(Light* light) : light(light), previousState(false) {}

    void execute() override {
        previousState = (/*假设Light有个getState()方法*/ false); // 实际应用中需要获取灯的当前状态
        light->turnOn();
    }

    void undo() override {
        if (previousState) {
            light->turnOn(); // 恢复到之前的状态(如果之前是开着的)
        } else {
            light->turnOff(); // 恢复到之前的状态(如果之前是关着的)
        }
    }
};

//Invoker (with Undo/Redo)
class RemoteControl {
private:
    std::vector<Command*> commandHistory;
    int currentCommandIndex = -1; // 指向当前执行的命令

public:
    void executeCommand(Command* command) {
        command->execute();
        if (currentCommandIndex < (int)commandHistory.size() - 1) {
            // 如果执行了undo之后的新命令,则清除后面的历史
            commandHistory.erase(commandHistory.begin() + currentCommandIndex + 1, commandHistory.end());
        }
        commandHistory.push_back(command);
        currentCommandIndex++;
    }

    void undo() {
        if (currentCommandIndex >= 0) {
            commandHistory[currentCommandIndex]->undo();
            currentCommandIndex--;
        }
    }

    void redo() {
        if (currentCommandIndex < (int)commandHistory.size() - 1) {
            currentCommandIndex++;
            commandHistory[currentCommandIndex]->execute();
        }
    }
};

int main() {
    Light* livingRoomLight = new Light();
    RemoteControl* remote = new RemoteControl();

    TurnOnCommand* turnOnCmd = new TurnOnCommand(livingRoomLight);
    TurnOffCommand* turnOffCmd = new TurnOffCommand(livingRoomLight);

    remote->executeCommand(turnOnCmd); // Light is ON
    remote->executeCommand(turnOffCmd); // Light is OFF

    remote->undo(); // Light is ON
    remote->undo(); // Light is OFF

    remote->redo(); // Light is ON
    remote->redo(); // Light is OFF

    delete turnOnCmd;
    delete turnOffCmd;
    delete livingRoomLight;
    delete remote;

    return 0;
}
登录后复制

注意,undo()的实现需要根据具体情况进行调整,通常需要记录命令执行前的状态。此外,撤销/重做功能的实现还需要考虑内存管理,避免内存泄漏。

命令模式和策略模式有什么区别

虽然命令模式和策略模式都涉及到封装,但它们的目的不同。命令模式封装的是请求,而策略模式封装的是算法。 命令模式的重点在于解耦请求的发送者和接收者,允许请求排队、记录日志等。 策略模式的重点在于提供一种在运行时选择算法的方式,使得算法可以独立于使用它的客户端而变化。 策略模式关注的是算法的可替换性,而命令模式关注的是请求的封装和执行。 简单来说,策略模式解决的是“用哪个算法”,命令模式解决的是“做什么操作”。

以上就是C++如何实现命令模式 C++命令模式的设计与示例的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号