C++命令模式撤销Redo/Undo实现

2026-04-02 16:20:17 1057阅读 0评论

C++命令模式撤销/重做(Redo/Undo)实现详解

在软件开发中,撤销和重做的功能是用户界面设计中的常见需求。通过这些功能,用户可以方便地回溯操作历史并恢复到之前的某个状态。本文将详细介绍如何在C++中使用命令模式来实现撤销和重做功能。

命令模式简介

命令模式是一种行为设计模式,它将请求封装成对象,从而使你可以用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作,这正是我们今天要探讨的重点。

主要角色

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

实现步骤

1. 定义命令接口

首先,我们需要定义一个命令接口,所有具体的命令都将继承这个接口。

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

2. 创建具体命令

接下来,我们需要为每个需要撤销和重做的操作创建一个具体命令类。

class TextEdit {
public:
    void insert(const std::string& text) { /* 插入文本 */ }
    void remove(int length) { /* 删除文本 */ }
};

class InsertTextCommand : public Command {
private:
    TextEdit* receiver;
    std::string text;

public:
    InsertTextCommand(TextEdit* r, const std::string& t) : receiver(r), text(t) {}

    void execute() override {
        receiver->insert(text);
    }

    void undo() override {
        receiver->remove(text.length());
    }
};

3. 实现调用者

调用者负责管理命令的执行和撤销操作。

class Editor {
private:
    std::vector<Command*> commands;
    int current = -1;

public:
    void executeCommand(Command* command) {
        if (current != commands.size() - 1) {
            commands.erase(commands.begin() + current + 1, commands.end());
        }
        commands.push_back(command);
        command->execute();
        ++current;
    }

    void undo() {
        if (current >= 0) {
            commands[current]->undo();
            --current;
        }
    }

    void redo() {
        if (current < commands.size() - 1) {
            ++current;
            commands[current]->execute();
        }
    }
};

4. 使用示例

最后,我们可以使用上述代码来实现一个简单的编辑器,并演示撤销和重做功能。

int main() {
    TextEdit editor;
    Editor app;

    auto cmd1 = new InsertTextCommand(&editor, "Hello");
    app.executeCommand(cmd1);

    auto cmd2 = new InsertTextCommand(&editor, ", World!");
    app.executeCommand(cmd2);

    app.undo(); // 取消插入 "World!"
    app.redo(); // 重新插入 "World!"

    return 0;
}

总结

通过使用命令模式,我们可以轻松地实现撤销和重做功能。这种设计模式不仅提高了代码的可维护性和可扩展性,还使得操作的历史记录可以被方便地管理和回溯。希望本文能帮助你更好地理解和应用命令模式,提升你的编程技能。

文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
验证码
评论列表 (暂无评论,1057人围观)

还没有评论,来说两句吧...

目录[+]