命令模式和备忘录模式实现undo、redo(C++)

命令模式:

**定义:**命令模式是一种行为型设计模式,它将一个请求封装成一个对象,从而允许使用不同的请求、队列或日志请求,并支持可撤销的操作。命令模式的核心思想是将请求的发送者与请求的接收者解耦,使得请求的发送者无需知道接收者的具体实现,从而提高了系统的灵活性和可维护性。

备忘录模式:

**定义:**备忘录模式是一种行为型设计模式,也叫做快照模式(Snapshot),它允许在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。备忘录模式主要用于实现撤销机制、版本控制、历史记录等功能。

**应用:**命令模式和备忘录模式在实现undo和redo功能时都发挥着重要作用。命令模式通过封装请求和提供撤销方法来实现撤销和重做功能;而备忘录模式则通过保存对象的状态来实现撤销和重做功能。在实际应用中,这两种模式可以相互结合使用,以构建更加灵活和可维护的系统。例如,在命令模式中引入备忘录模式来保存命令执行前后的状态,从而更方便地实现撤销和重做功能。

代码:

cpp 复制代码
// 接收者类,包含可以执行的状态
class Receiver {
private:
    std::string state;

public:
    std::string getState() const { return state; }
    void setState(const std::string& newState) { state = newState; }
};


// 定义一个接口类,用于所有命令
class Command {
public:
    virtual ~Command() = default;
    virtual void execute() = 0;
    virtual void undo() = 0;
};

// 具体的命令类
class ConcreteCommand : public Command {
private:
    std::shared_ptr<Receiver> receiver;
    std::string previousState;
    std::string newState;

public:
    ConcreteCommand(std::shared_ptr<Receiver> r, const std::string& state)
        : receiver(r), newState(state) {}

    void execute() override {
        previousState = receiver->getState();
        receiver->setState(newState);
        std::cout << "Executed: " << newState << std::endl;
    }

    void undo() override {
        receiver->setState(previousState);
        std::cout << "Undone: " << previousState << std::endl;
    }
};

// 调用者类,包含撤销和重做功能的实现
class Invoker {
private:
    std::stack<std::shared_ptr<Command>> undoStack;
    std::stack<std::shared_ptr<Command>> redoStack;

public:
    void executeCommand(std::shared_ptr<Command> command) {
        command->execute();
        undoStack.push(command);
        while (!redoStack.empty()) // 执行新命令时清空重做栈
        {
            redoStack.pop();
        }
    }

    void undo() {
        if (!undoStack.empty()) {
            auto command = undoStack.top();
            undoStack.pop();
            command->undo();
            redoStack.push(command);
        } else {
            std::cout << "No more commands to undo." << std::endl;
        }
    }

    void redo() {
        if (!redoStack.empty()) {
            auto command = redoStack.top();
            redoStack.pop();
            command->execute();
            undoStack.push(command);
        } else {
            std::cout << "No more commands to redo." << std::endl;
        }
    }
};

int main() {
    std::shared_ptr<Receiver> receiver = std::make_shared<Receiver>();
    Invoker invoker;

    receiver->setState("State1");

    invoker.executeCommand(std::make_shared<ConcreteCommand>(receiver, "State2"));
    invoker.executeCommand(std::make_shared<ConcreteCommand>(receiver, "State3"));

    invoker.undo();
    invoker.undo();

    invoker.redo();

    return 0;
}
相关推荐
啦啦啦啦啦zzzz3 小时前
自定义日志缓冲区(上)c++20
linux·服务器·c++·网络编程
wabs6663 小时前
关于二叉树【力扣199.二叉树的右视图的思考】
数据结构·c++·算法·leetcode·二叉树·层序遍历
hope_wisdom3 小时前
C/C++数据结构之二叉树的遍历
c语言·数据结构·c++·二叉树·深度优先·广度优先
cpp_learner4 小时前
C++ 实现责任链模式(Chain of Responsibility):从一堆 if-else 到可插拔的处理管道
c++·设计模式
一木 之林4 小时前
五、C++ 新特性、关键字与编译原理(进阶)(一)
c语言·开发语言·c++
2601_962298274 小时前
交易开拓者通常使用什么编程语言?这种语言如何帮助自动化交易?
java·c++·python·编程语言·自动化交易
码匠许师傅4 小时前
【设计模式精讲】23.备忘录模式(Memento)
c++·设计模式·软件工程·uml·备忘录模式
键盘会跳舞5 小时前
【C++多线程】thread_local 深度剖析:线程局部存储的生命周期与实现
c++·多线程·thread_local
whitelbwwww5 小时前
c++ 多线程
开发语言·c++·算法
努力努力再努力wz5 小时前
【Docker入门系列】:从架构演进到容器化:一文建立 Docker、虚拟化与 Namespace 的底层心智模型
运维·开发语言·数据结构·c++·docker·容器·架构