备忘录模式 (Memento Pattern)

发布于:2024-12-06 ⋅ 阅读:(93) ⋅ 点赞:(0)

备忘录模式 (Memento Pattern)

备忘录模式是一种 行为型设计模式,用于保存对象的某个状态,以便在需要时可以恢复到该状态。它是一种用于撤销和恢复的设计模式。


原理

  1. 核心思想
    • 在不破坏对象封装的前提下,捕获并存储对象的内部状态。
    • 恢复时,通过备忘录对象还原对象的状态。
  2. 适用场景
    • 需要保存对象的历史状态,并在需要时可以恢复。
    • 需要实现撤销操作。
  3. 参与角色
    • Originator(发起者)
      • 负责创建备忘录,并可以通过备忘录恢复其内部状态。
    • Memento(备忘录)
      • 存储发起者的内部状态,提供发起者状态的备份。
    • Caretaker(管理者)
      • 负责保存备忘录,但不修改或访问备忘录内容。

优点

  1. 封装性
    • 保存对象状态时,不暴露对象的内部细节。
  2. 撤销功能
    • 支持多级恢复,使程序更加灵活。
  3. 简化管理
    • 使用备忘录集中管理历史状态。

缺点

  1. 内存开销
    • 需要保存对象的历史状态,可能导致内存消耗较大。
  2. 实现复杂性
    • 复杂对象的状态备份和恢复可能较为困难。

示例代码

场景描述

实现一个文本编辑器,支持保存文本状态和撤销操作。


1. 定义备忘录类
// 备忘录类
public class Memento {
    private final String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}

2. 定义发起者类
// 发起者类
public class TextEditor {
    private String text;

    public void setText(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }

    // 创建备忘录
    public Memento save() {
        return new Memento(text);
    }

    // 从备忘录恢复状态
    public void restore(Memento memento) {
        this.text = memento.getState();
    }
}

3. 定义管理者类
import java.util.Stack;

// 管理者类
public class Caretaker {
    private final Stack<Memento> history = new Stack<>();

    // 保存状态
    public void save(Memento memento) {
        history.push(memento);
    }

    // 获取上一个状态
    public Memento undo() {
        if (!history.isEmpty()) {
            return history.pop();
        }
        return null;
    }
}

4. 客户端代码
public class MementoPatternExample {
    public static void main(String[] args) {
        TextEditor editor = new TextEditor();
        Caretaker caretaker = new Caretaker();

        // 编辑文本
        editor.setText("Hello");
        caretaker.save(editor.save()); // 保存状态
        System.out.println("Saved Text: " + editor.getText());

        editor.setText("Hello, World!");
        caretaker.save(editor.save()); // 保存状态
        System.out.println("Updated Text: " + editor.getText());

        editor.setText("Hello, World! How are you?");
        System.out.println("Current Text: " + editor.getText());

        // 撤销操作
        editor.restore(caretaker.undo());
        System.out.println("After Undo 1: " + editor.getText());

        editor.restore(caretaker.undo());
        System.out.println("After Undo 2: " + editor.getText());
    }
}

输出结果
Saved Text: Hello
Updated Text: Hello, World!
Current Text: Hello, World! How are you?
After Undo 1: Hello, World!
After Undo 2: Hello

UML 类图

        +-----------------+
        |    Originator   |
        +-----------------+
        | - state : String|
        | + save(): Memento|
        | + restore(Memento)|
        +-----------------+
               |
               v
        +-----------------+
        |    Memento      |
        +-----------------+
        | - state : String|
        | + getState()    |
        +-----------------+
               ^
               |
        +-----------------+
        |   Caretaker     |
        +-----------------+
        | - history : Stack|
        | + save(Memento)  |
        | + undo(): Memento|
        +-----------------+

使用场景

  1. 撤销操作
    • 文本编辑器、图形编辑器等应用场景。
  2. 事务管理
    • 数据库事务的回滚机制。
  3. 游戏存档
    • 游戏状态的保存与恢复。

扩展与优化

  1. 压缩存储
    • 对大对象的备份进行压缩,以减少内存占用。
  2. 增量备份
    • 仅保存与上一个状态的差异,而非整个状态。
  3. 多级撤销与重做
    • 使用双栈实现撤销与重做功能。

小结

  • 备忘录模式是一种非常实用的模式,特别是在需要状态保存与恢复的场景中。
  • 应根据实际需求选择适当的存储方式,避免因备忘录数量过多而导致的资源浪费。
  • 常见于文本编辑器、游戏存档、事务管理等领域。