【设计模式系列笔记】备忘录模式

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不暴露对象实现细节的情况下捕获并恢复其内部状态。这种模式属于行为型设计模式。备忘录模式通常包含以下几个角色:发起人,备忘录,管理者。

1. 备忘录模式介绍

备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不暴露对象实现细节的情况下捕获并恢复其内部状态。这种模式属于行为型设计模式。

备忘录模式通常包含以下几个角色:

  1. 发起人(Originator):负责创建一个包含其当前内部状态的备忘录,并使用备忘录恢复内部状态。它是需要被备份和恢复状态的对象。
  2. 备忘录(Memento):存储发起人对象的内部状态。备忘录可以包含发起人对象的全部状态,也可以只包含部分状态,具体取决于需要保存的信息。
  3. 管理者(Caretaker):负责保存备忘录,并在需要的时候将其提供给发起人以进行状态恢复。管理者不应该直接修改备忘录的内容。

2. 关键思想

备忘录模式的关键思想是在不破坏对象封装的前提下,捕获对象的内部状态,并在之后能够将对象恢复到之前的状态。它提供了一种在对象之间保持状态的机制,使得对象能够在不暴露其实现细节的情况下进行状态的保存和还原。

以下是备忘录模式的关键思想:

  1. 封装对象状态: 对象的状态被封装在备忘录对象中。这确保了对象的实现细节对外部是不可见的,从而提高了对象的封装性。
  2. 备份和恢复状态: 发起人对象负责创建备忘录对象,并将其内部状态保存到备忘录中。这样,在需要的时候,可以使用备忘录来还原对象的状态。
  3. 单一职责原则: 备忘录模式使得对象负责自己的状态,而备忘录对象负责存储状态。这有助于遵循单一职责原则,即一个类应该只有一个引起变化的原因。
  4. 管理备忘录: 管理者对象(Caretaker)负责保存和管理备忘录对象。管理者不应该修改备忘录的内容,它只负责存储备忘录,以便在需要时将其提供给发起人对象。
  5. 支持撤销操作: 备忘录模式通常与撤销操作结合使用。通过保存对象的历史状态,可以轻松地实现撤销操作,即将对象恢复到之前的状态。

备忘录模式在实际应用中常用于需要记录对象状态历史、支持撤销/重做功能或者需要进行状态回滚的场景。通过将状态保存在备忘录中,可以有效地管理对象的状态变化。

3. 实现方式

备忘录模式的实现方式通常涉及三个主要角色:发起人(Originator)、备忘录(Memento)和管理者(Caretaker)。以下是备忘录模式的一般实现步骤:

  1. 创建备忘录类(Memento):
  • 定义备忘录类,用于存储发起人对象的内部状态。
  • 备忘录可以包含发起人对象的全部或部分状态,具体取决于需要保存的信息。
/**
 * 备忘录类表示发起人内部状态的快照。
 * 它存储状态信息并提供了一种检索状态的方法。
 */
public class Memento {
    private String state;
    /**
     * 构造函数,用于使用给定状态创建新的备忘录。
     *
     * @param state 要存储在备忘录中的状态。
     */
    public Memento(String state) {
        this.state = state;
    }
    /**
     * 从备忘录中检索存储的状态。
     *
     * @return 存储的状态。
     */
    public String getState() {
        return state;
    }
}
  1. 创建发起人类(Originator):
  • 发起人负责创建备忘录对象,并将其内部状态保存到备忘录中。
  • 发起人还可以从备忘录中恢复状态。
/**
 * 发起人类负责创建备忘录对象、保存和恢复内部状态。
 */
public class Originator {
    private String state;
    /**
     * 设置发起人的状态。
     *
     * @param state 要设置的状态。
     */
    public void setState(String state) {
        this.state = state;
    }
    /**
     * 获取发起人的当前状态。
     *
     * @return 当前状态。
     */
    public String getState() {
        return state;
    }
    /**
     * 创建并返回一个包含当前状态的备忘录对象。
     *
     * @return 包含当前状态的备忘录对象。
     */
    public Memento saveStateToMemento() {
        return new Memento(state);
    }
    /**
     * 从备忘录中恢复发起人的状态。
     *
     * @param memento 包含要恢复的状态的备忘录对象。
     */
    public void restoreStateFromMemento(Memento memento) {
        state = memento.getState();
    }
}
  1. 创建管理者类(Caretaker):
  • 管理者负责保存备忘录对象,可以保存多个备忘录,以便支持多步的撤销和重做操作。
import java.util.ArrayList;
import java.util.List;
/**
 * 管理者类负责保存和提供备忘录对象。
 */
public class Caretaker {
    private List<Memento> mementoList = new ArrayList<>();
    /**
     * 将备忘录对象添加到备忘录列表中。
     *
     * @param memento 要添加的备忘录对象。
     */
    public void addMemento(Memento memento) {
        mementoList.add(memento);
    }
    /**
     * 根据索引从备忘录列表中获取备忘录对象。
     *
     * @param index 要获取的备忘录对象的索引。
     * @return 获取到的备忘录对象。
     */
    public Memento getMemento(int index) {
        return mementoList.get(index);
    }
}
  1. 客户端使用备忘录模式:
  • 在客户端代码中,创建发起人对象、管理者对象,通过发起人对象保存和恢复状态。
/**
 * 客户端代码用于演示备忘录模式的使用。
 */
public class Client {
    public static void main(String[] args) {
        // 创建发起人和管理者对象
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();
        // 保存状态
        originator.setState("状态1");
        caretaker.addMemento(originator.saveStateToMemento());
        // 修改状态
        originator.setState("状态2");
        caretaker.addMemento(originator.saveStateToMemento());
        // 恢复状态
        originator.restoreStateFromMemento(caretaker.getMemento(0));
    }
}

在上述代码中,客户端通过创建发起人对象、备忘录对象和管理者对象,实现了对发起人对象状态的保存和恢复。这样,客户端就能够在不破坏对象封装的情况下管理对象的状态。

要点:

  1. 封装性: 备忘录模式能够在不暴露对象实现细节的情况下保存和恢复其状态,从而增强了对象的封装性。
  2. 状态管理: 通过备忘录模式,可以有效地管理对象的状态,使得对象能够在不同的时间点恢复到先前的状态。
  3. 支持撤销和重做: 备忘录模式常与撤销操作结合使用,支持撤销和重做功能。通过保存对象的历史状态,可以轻松实现这些操作。
  4. 多状态保存: 一个发起人对象可以创建多个备忘录对象,从而保存不同时间点的状态。这为多状态的管理提供了灵活性。

注意事项:

  1. 内存占用: 保存大量的备忘录对象可能会占用较大的内存,特别是在需要保存大量状态时。在设计时需权衡内存占用和系统性能。
  2. 备忘录可见性: 备忘录对象的内容一般不应该对外部直接可见或可修改,以保持对象状态的一致性。应该通过发起人对象提供的接口进行状态的恢复和查询。
  3. 性能开销: 创建和管理备忘录对象可能会带来性能开销,尤其是在需要频繁保存状态时。在性能敏感的应用中,需谨慎使用备忘录模式。
  4. 合理使用场景: 备忘录模式适用于需要保存和还原对象状态的场景,如撤销机制、历史记录、事务管理等。在某些情况下,其他设计模式可能更合适。

总体而言,备忘录模式是一种强大的模式,但在具体应用时需要根据系统需求和性能考虑来合理设计和使用。

优点:

  1. 封装性: 备忘录模式实现了对象状态的封装,将状态存储在备忘录对象中,从而避免了直接暴露对象内部实现细节。
  2. 撤销和重做: 提供了良好的撤销和重做机制。通过保存对象历史状态,可以轻松实现撤销和重做功能。
  3. 状态管理: 有效地管理对象状态,允许在不同时间点保存和还原对象的状态,提供了一种灵活的状态管理方式。
  4. 简化原发器实现: 备忘录模式使得原发器对象不必关心状态的保存和还原,将这一责任交给备忘录对象处理,简化了原发器的实现。
  5. 多状态保存: 允许发起人对象保存多个状态,为多状态管理提供了支持。

缺点:

  1. 内存占用: 当需要保存大量的状态时,备忘录模式可能会占用较大的内存,因为每个备忘录对象都需要存储一份完整的状态。
  2. 性能开销: 创建和管理备忘录对象可能带来一定的性能开销,尤其在需要频繁保存状态的情况下。

应用场景:

  1. 撤销机制: 当需要实现撤销操作时,备忘录模式是一个非常实用的设计模式。通过保存对象的历史状态,可以轻松实现撤销功能。
  2. 事务管理: 在数据库系统等需要事务管理的应用中,备忘录模式可以用于保存事务的状态,以支持事务的回滚。
  3. 编辑器历史记录: 图形编辑器、文本编辑器等应用可以使用备忘录模式来保存用户的编辑历史,以支持撤销和重做功能。
  4. 游戏状态管理: 在游戏开发中,备忘录模式可以用于保存游戏状态,以支持玩家在游戏中的存档和加载功能。
  5. 工作流程管理: 在需要管理复杂工作流程状态的系统中,备忘录模式可以用于保存和还原工作流程的状态。

备忘录模式在需要保存和还原对象状态的场景中表现出色,特别是在需要支持撤销和重做功能的应用中。然而,在使用时需要权衡其优缺点,并根据具体情况选择是否采用备忘录模式。

目录
相关文章
|
19天前
|
设计模式 Java API
Kotlin教程笔记(50) - 改良设计模式 - 工厂模式
Kotlin教程笔记(50) - 改良设计模式 - 工厂模式
|
19天前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
|
19天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
|
1月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
29 2
|
14天前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
14天前
|
设计模式 Java Kotlin
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
|
14天前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
25 3
|
14天前
|
设计模式 算法 Kotlin
Kotlin教程笔记(53) - 改良设计模式 - 策略模式
Kotlin教程笔记(53) - 改良设计模式 - 策略模式
41 2
|
14天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
36 1
|
14天前
|
设计模式 Java API
Kotlin教程笔记(50) - 改良设计模式 - 工厂模式
Kotlin教程笔记(50) - 改良设计模式 - 工厂模式
22 1