2023-7-24-第二十二式备忘录模式

简介: 2023-7-24-第二十二式备忘录模式

😉一、基础概念

备忘录模式是一种软件设计模式,用于在不破坏封装性的情况下保存和恢复对象的内部状态。它允许将对象的状态保存到一个称为备忘录的中介者(或备份)中,并在需要时从中恢复。这样可以有效地实现撤销操作、历史记录功能或者以某种方式回滚对象的状态。

备忘录模式由三个主要角色组成:

  1. 发起人(Originator):发起人是包含需要保存状态的对象。它可以创建并保存当前状态到备忘录中,或者从备忘录中恢复之前保存的状态。
  2. 备忘录(Memento):备忘录是存储发起人对象状态的中介者。它提供了一种封装机制,确保只有发起人对象可以访问其内部状态。
  3. 管理者(Caretaker):管理者负责保存和恢复备忘录。它可以存储多个备忘录对象,并按需调用备忘录的保存和恢复方法。

使用备忘录模式可以使对象的状态管理更加灵活,同时也遵循了面向对象设计原则中的封装与单一职责原则。该模式在需要实现撤销、重做、历史记录等功能时非常有用,并且能够简化代码的复杂性。


🐱‍🐉二、备忘录模式实现

在 C++ 中实现备忘录模式,我们可以按照以下步骤进行:

  1. 定义发起人类(Originator):发起人类是需要保存状态的对象。它包含要保存和恢复的数据成员,并提供创建备忘录、从备忘录中恢复状态的方法。
class Originator {
private:
    std::string state;
public:
    void setState(const std::string& newState) {
        state = newState;
    }
    std::string getState() const {
        return state;
    }
    Memento createMemento() const {
        return Memento(state);
    }
    void restoreFromMemento(const Memento& memento) {
        state = memento.getState();
    }
};
  1. 定义备忘录类(Memento):备忘录类用于存储发起人对象的状态。它包含一个或多个与发起人对象相关的数据成员,并提供获取和设置状态的方法。
class Memento {
private:
    std::string state;
public:
    Memento(const std::string& newState) : state(newState) {}
    std::string getState() const {
        return state;
    }
};
  1. 定义管理者类(Caretaker):管理者类负责保存和恢复备忘录。它可以存储多个备忘录对象,并提供保存和获取备忘录的方法。
class Caretaker {
private:
    std::vector<Memento> mementos;
public:
    void addMemento(const Memento& memento) {
        mementos.push_back(memento);
    }
    Memento getMemento(int index) const {
        return mementos[index];
    }
};

现在,我们可以使用这些类进行测试:

int main() {
    Originator originator;
    Caretaker caretaker;
    // 设置初始状态
    originator.setState("State A");
    // 保存当前状态到备忘录
    caretaker.addMemento(originator.createMemento());
    // 修改状态
    originator.setState("State B");
    // 再次保存当前状态到备忘录
    caretaker.addMemento(originator.createMemento());
    // 恢复到第一个备忘录的状态
    originator.restoreFromMemento(caretaker.getMemento(0));
    std::cout << "Current state: " << originator.getState() << std::endl;  // 输出:Current state: State A
    return 0;
}

在上述示例中,我们创建了一个发起人对象 originator 和一个管理者对象 caretaker。通过设置和修改发起人对象的状态,并使用备忘录保存和恢复操作,我们可以验证备忘录模式的实现。


🎉三、模块之间的关系

在备忘录模式中,有三个主要的角色:发起人(Originator)、备忘录(Memento)和管理者(Caretaker)。它们之间的关系如下:

  1. 发起人(Originator):发起人是包含需要保存状态的对象。它负责创建备忘录对象并将自身的状态保存到备忘录中,或者从备忘录中恢复之前保存的状态。发起人可以直接访问备忘录对象的状态。
  2. 备忘录(Memento):备忘录是存储发起人对象状态的中介者。它提供了一种封装机制,确保只有发起人对象可以访问其内部状态。备忘录类通常只包含与发起人对象相关的数据成员,并提供获取和设置状态的方法。
  3. 管理者(Caretaker):管理者负责保存和恢复备忘录。它可以存储多个备忘录对象,并按需调用备忘录的保存和恢复方法。管理者对象不知道具体的备忘录结构,只负责管理备忘录对象的集合。

下面是备忘录模式中这些角色之间的交互流程:

  1. 发起人对象通过调用 createMemento 方法创建一个备忘录对象,并将自身的状态保存到备忘录中。
  2. 发起人对象可以通过调用 getState 方法获取当前状态,并通过 setState 方法修改状态。
  3. 发起人对象可以使用备忘录对象的数据,但不能直接访问备忘录对象内部的数据成员。
  4. 管理者对象负责保存备忘录对象。它使用 addMemento 方法将备忘录对象添加到一个集合中,并使用 getMemento 方法从集合中获取备忘录对象。
  5. 恢复先前状态时,发起人对象调用 restoreFromMemento 方法,并传递所需的备忘录对象。发起人对象根据备忘录对象中保存的状态恢复自身的状态。

因此,备忘录模式的关系是一种单向的、松散的耦合关系,其中发起人对象控制着备忘录的创建和恢复过程,而管理者对象负责保存和提供备忘录对象,以实现状态的保存和恢复。


🐱‍🚀四、注意事项

在使用备忘录模式时,有一些注意事项需要考虑:

  1. 备忘录对象的封装性:备忘录对象应该被设计为只有发起人对象能够访问和修改其内部状态。这样可以确保备忘录模式的封装性,防止其他对象直接访问和修改备忘录对象的状态。
  2. 对象状态的保存和恢复:发起人对象应该负责将自身的状态保存到备忘录中,并从备忘录中恢复状态。确保在合适的时间和位置调用相应的保存和恢复方法,以实现正确的状态管理。
  3. 管理者对象的职责:管理者对象负责保存和提供备忘录对象,但并不了解备忘录的具体结构。管理者对象应该限制对备忘录的访问,并只提供必要的方法来保存和获取备忘录对象。
  4. 内存消耗的考虑:备忘录模式可能会导致内存消耗较大,特别是当需要保存大量的状态或历史记录时。在设计时需要权衡内存效率和功能需求,避免过度使用备忘录对象。
  5. 可撤销操作的处理:备忘录模式常用于实现撤销操作、重做功能或历史记录。在实现中,需要确保发起人对象和管理者对象之间的协调,以便正确地保存和恢复状态,实现可撤销操作的逻辑。

综上所述,备忘录模式是一种有用的设计模式,可以实现对象状态的保存和恢复。在使用时需要注意封装性、状态的保存与恢复、管理者对象的职责、内存消耗以及可撤销操作的处理等方面的考虑。


🎂五、使用场景

备忘录模式适用于以下场景:

  1. 需要实现撤销和恢复功能:备忘录模式可以用于保存对象的历史状态,以便在需要时进行撤销操作或恢复到之前的状态。例如,在文本编辑器中可以使用备忘录模式实现撤销和重做功能。
  2. 需要记录对象状态历史记录:如果需要跟踪和记录对象的状态变化历史,备忘录模式是一种有效的设计模式。它可以让对象保存不同时间点的状态,并在需要时查看或还原这些状态。例如,在游戏中可以使用备忘录模式记录玩家的游戏进度。
  3. 需要实现快照功能:备忘录模式可以用于实现快照功能,即在特定时间点保存对象的完整状态。这样可以随时恢复对象到该时间点的状态。例如,在虚拟机中可以使用备忘录模式保存虚拟机的快照,以便在需要时恢复到该快照。
  4. 需要实现数据版本控制:备忘录模式可以用于实现数据版本控制,特别是在多用户环境下对数据进行并发修改的情况。备忘录模式可以帮助记录和管理不同版本的数据状态,从而实现数据的版本控制和冲突解决。

总而言之,备忘录模式适用于需要保存、恢复或跟踪对象状态的场景。它提供了一种灵活的方式来管理对象状态,并可以在需要时进行撤销、历史记录或版本控制等操作。


🍳参考文献

🧊文章总结

提示:这里对文章进行总结:

   本文讲了关于备忘录模式的知识。


目录
相关文章
|
监控 Java 应用服务中间件
SpringBoot3---核心特性---1、快速入门
SpringBoot3---核心特性---1、快速入门
|
存储 缓存 5G
时域结构 | 带你读《5G 空口设计与实践进阶 》之十七
在时域,NR 支持基于符号灵活定义的帧结构,以满足各种时延需求。
时域结构 | 带你读《5G 空口设计与实践进阶 》之十七
|
9月前
|
人工智能 并行计算 Linux
斯坦福黑科技让笔记本GPU也能玩转AI视频生成!FramePack:压缩输入帧上下文长度!仅需6GB显存即可生成高清动画
斯坦福大学推出的FramePack技术通过压缩输入帧上下文长度,解决视频生成中的"遗忘"和"漂移"问题,仅需6GB显存即可在普通笔记本上实时生成高清视频。
2196 19
斯坦福黑科技让笔记本GPU也能玩转AI视频生成!FramePack:压缩输入帧上下文长度!仅需6GB显存即可生成高清动画
|
Prometheus Kubernetes 监控
OpenAI故障复盘 - 阿里云容器服务与可观测产品如何保障大规模K8s集群稳定性
聚焦近日OpenAI的大规模K8s集群故障,介绍阿里云容器服务与可观测团队在大规模K8s场景下我们的建设与沉淀。以及分享对类似故障问题的应对方案:包括在K8s和Prometheus的高可用架构设计方面、事前事后的稳定性保障体系方面。
|
安全 Android开发 iOS开发
深入探索iOS与Android系统的差异性及优化策略
在当今数字化时代,移动操作系统的竞争尤为激烈,其中iOS和Android作为市场上的两大巨头,各自拥有庞大的用户基础和独特的技术特点。本文旨在通过对比分析iOS与Android的核心差异,探讨各自的优势与局限,并提出针对性的优化策略,以期为用户提供更优质的使用体验和为开发者提供有价值的参考。
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
存储 机器学习/深度学习 并行计算
阿里云服务器X86计算、Arm计算、GPU/FPGA/ASIC、高性能计算架构区别
在我们选购阿里云服务器的时候,云服务器架构有X86计算、ARM计算、GPU/FPGA/ASIC、弹性裸金属服务器、高性能计算可选,有的用户并不清楚他们之间有何区别,本文主要简单介绍下不同类型的云服务器有何不同,主要特点及适用场景有哪些。
阿里云服务器X86计算、Arm计算、GPU/FPGA/ASIC、高性能计算架构区别
|
前端开发 JavaScript
React的事件与原生事件的执行顺序?
React的事件与原生事件的执行顺序?
|
机器学习/深度学习 数据采集 存储
一文读懂蒙特卡洛算法:从概率模拟到机器学习模型优化的全方位解析
蒙特卡洛方法起源于1945年科学家斯坦尼斯劳·乌拉姆对纸牌游戏中概率问题的思考,与约翰·冯·诺依曼共同奠定了该方法的理论基础。该方法通过模拟大量随机场景来近似复杂问题的解,因命名灵感源自蒙特卡洛赌场。如今,蒙特卡洛方法广泛应用于机器学习领域,尤其在超参数调优、贝叶斯滤波等方面表现出色。通过随机采样超参数空间,蒙特卡洛方法能够高效地找到优质组合,适用于处理高维度、非线性问题。本文通过实例展示了蒙特卡洛方法在估算圆周率π和优化机器学习模型中的应用,并对比了其与网格搜索方法的性能。
1517 1
|
存储 缓存 NoSQL
详解布隆过滤器原理与实现
详解布隆过滤器原理与实现

热门文章

最新文章