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

C++实现设计模式---备忘录模式 (Memento)

备忘录模式 (Memento)

备忘录模式 是一种行为型设计模式,它允许在不破坏封装的前提下,捕获和恢复对象的内部状态。通过备忘录模式,可以在程序运行时存储某个对象的历史状态,并在需要时恢复。


意图

  • 提供一种方法,在不破坏对象封装性的前提下捕获和恢复其内部状态。
  • 通过备忘录存储对象的历史状态,便于实现撤销、重做功能。

使用场景

  1. 需要保存对象的历史状态
    • 如文本编辑器中的撤销、恢复功能。
  2. 需要在程序运行时回滚对象状态
    • 如游戏中存储和恢复玩家进度。
  3. 希望避免暴露对象的实现细节
    • 通过备忘录隐藏对象的内部状态。

参与者角色

  1. 发起人 (Originator)
    • 定义一个创建和恢复备忘录的接口,负责存储对象的内部状态。
  2. 备忘录 (Memento)
    • 存储发起人对象的内部状态。
    • 对发起人以外的其他对象是不可变的。
  3. 管理者 (Caretaker)
    • 负责保存和恢复备忘录,但无法访问备忘录的内容。

示例代码

以下代码展示了备忘录模式的实现,用于模拟一个文本编辑器的撤销和恢复功能。

#include <iostream>
#include <string>
#include <vector>
#include <memory>

// 备忘录类:存储文本状态
class Memento {
private:
    std::string state;

public:
    explicit Memento(const std::string& state) : state(state) {}

    std::string getState() const {
        return state;
    }
};

// 发起人类:文本编辑器
class TextEditor {
private:
    std::string text;

public:
    void appendText(const std::string& newText) {
        text += newText;
    }

    void setText(const std::string& newText) {
        text = newText;
    }

    std::string getText() const {
        return text;
    }

    // 创建备忘录
    std::unique_ptr<Memento> save() const {
        return std::make_unique<Memento>(text);
    }

    // 恢复状态
    void restore(const Memento& memento) {
        text = memento.getState();
    }
};

// 管理者类:管理备忘录
class Caretaker {
private:
    std::vector<std::unique_ptr<Memento>> history;

public:
    void save(std::unique_ptr<Memento> memento) {
        history.push_back(std::move(memento));
    }

    const Memento* undo() {
        if (!history.empty()) {
            const Memento* memento = history.back().get();
            history.pop_back();
            return memento;
        }
        return nullptr;
    }
};

// 客户端代码
int main() {
    TextEditor editor;
    Caretaker caretaker;

    editor.appendText("Hello");
    caretaker.save(editor.save()); // 保存状态

    editor.appendText(", World!");
    caretaker.save(editor.save()); // 保存状态

    editor.appendText(" Welcome to the Memento Pattern.");

    std::cout << "当前文本: " << editor.getText() << "
";

    // 撤销操作
    const Memento* memento = caretaker.undo();
    if (memento) {
        editor.restore(*memento);
        std::cout << "撤销后文本: " << editor.getText() << "
";
    }

    memento = caretaker.undo();
    if (memento) {
        editor.restore(*memento);
        std::cout << "再次撤销后文本: " << editor.getText() << "
";
    }

    return 0;
}

代码解析

1. 备忘录类 (Memento)
  • 存储发起人对象的内部状态,并提供一个方法获取状态。
  • 对其他对象不可变,只有发起人可以访问和修改它的内容。
class Memento {
private:
    std::string state;

public:
    explicit Memento(const std::string& state) : state(state) {}

    std::string getState() const {
        return state;
    }
};
2. 发起人类 (TextEditor)
  • 负责创建和恢复备忘录。
  • 提供 save 方法创建备忘录和 restore 方法恢复备忘录中的状态。
class TextEditor {
private:
    std::string text;

public:
    void appendText(const std::string& newText) {
        text += newText;
    }

    std::unique_ptr<Memento> save() const {
        return std::make_unique<Memento>(text);
    }

    void restore(const Memento& memento) {
        text = memento.getState();
    }
};
3. 管理者类 (Caretaker)
  • 保存和管理备忘录对象的历史。
  • 提供 save 方法保存备忘录,和 undo 方法实现状态回滚。
class Caretaker {
private:
    std::vector<std::unique_ptr<Memento>> history;

public:
    void save(std::unique_ptr<Memento> memento) {
        history.push_back(std::move(memento));
    }

    const Memento* undo() {
        if (!history.empty()) {
            const Memento* memento = history.back().get();
            history.pop_back();
            return memento;
        }
        return nullptr;
    }
};
4. 客户端代码
  • 客户端通过 TextEditor 创建和恢复状态,Caretaker 保存备忘录。

优缺点

优点
  1. 封装性
    • 备忘录对象对其他类是不可变的,保护了发起人的内部状态。
  2. 简化撤销/恢复操作
    • 通过备忘录存储历史状态,可以轻松实现撤销和恢复功能。
  3. 符合单一职责原则
    • 发起人和管理者各自负责不同的功能。
缺点
  1. 内存开销
    • 每次保存状态都会创建一个备忘录对象,可能占用较多内存。
  2. 实现复杂性
    • 需要额外的类来管理和存储备忘录。

适用场景

  1. 需要存储对象的历史状态
    • 如撤销功能、版本控制等场景。
  2. 需要恢复对象状态
    • 如游戏进度存储和恢复。
  3. 希望对象状态的存储和恢复对外透明
    • 通过备忘录隐藏内部实现细节。

总结

备忘录模式通过存储对象的历史状态,实现了状态的保存和恢复功能。它特别适用于需要撤销操作或恢复特定状态的场景。虽然会增加内存开销,但其封装性和操作的便利性使其在许多应用中非常有用。


http://www.kler.cn/a/503636.html

相关文章:

  • 正则表达式匹配任意字符的符号在哪
  • C++中的STL
  • HTML5 教程(上)
  • 基于 Python 的学生成绩管理系统设计与实现
  • shell脚本(二)
  • 最优控制 (Optimal Control) 算法详解及案例分析
  • List 接口的实现类
  • shell脚本练习(5)
  • 【大厂面试AI算法题中的知识点】方向涉及:ML/DL/CV/NLP/大数据...本篇介绍训练网络的时候如何判断过拟合和欠拟合?
  • redis缓存篇知识点总结
  • 详解英语单词“pro bono”:公益服务的表达(中英双语)
  • Vue2实现上传图片到阿里云的OSS对象存储
  • 《淘宝买家秀 API 爬虫:Java 实现与数据解析》
  • vim将一行行尾倒数第三个字符替换成1
  • Latent Diffusion Models
  • 51_Lua面向对象编程
  • 【解决问题】module加载不到 无法加载 1 Configuration module could not be loaded
  • Docker常用命令大全
  • 穿越科技长廊,VR科技展厅用科技之光点亮你的梦想之路
  • Angular-生命周期及钩子函数