Skip to content

备忘录

更新: 6/22/2025 字数: 0 字 时长: 0 分钟

定义

备忘录模式 (Memento Pattern) 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。它提供了状态恢复机制,支持撤销操作。

角色

  • 发起人 (Originator):创建备忘录对象,记录当前状态
  • 备忘录 (Memento):存储发起人的内部状态
  • 管理者 (Caretaker):保存备忘录对象,不操作备忘录内容
  • 客户端 (Client):使用发起人和管理者进行状态保存和恢复

实现

文本编辑器撤销功能

java
// 备忘录:存储编辑器状态
public class EditorMemento {
    private final String content;
    
    public EditorMemento(String content) {
        this.content = content;
    }
    
    public String getContent() {
        return content;
    }
}

// 发起人:文本编辑器
public class TextEditor {
    private String content;
    
    public void write(String text) {
        content = text;
    }
    
    public String getContent() {
        return content;
    }
    
    // 创建备忘录
    public EditorMemento createMemento() {
        return new EditorMemento(content);
    }
    
    // 从备忘录恢复
    public void restoreFromMemento(EditorMemento memento) {
        content = memento.getContent();
    }
}

// 管理者:保存历史状态
public class History {
    private Stack<EditorMemento> history = new Stack<>();
    
    public void save(EditorMemento memento) {
        history.push(memento);
    }
    
    public EditorMemento undo() {
        if (!history.isEmpty()) {
            return history.pop();
        }
        return null;
    }
}

// 客户端使用
public class TextEditorDemo {
    public static void main(String[] args) {
        TextEditor editor = new TextEditor();
        History history = new History();
        
        // 编辑并保存状态
        editor.write("第一版内容");
        history.save(editor.createMemento());
        
        // 修改内容
        editor.write("第二版内容");
        history.save(editor.createMemento());
        
        // 修改内容
        editor.write("第三版内容");
        System.out.println("当前内容:" + editor.getContent());
        
        // 撤销到上一版本
        editor.restoreFromMemento(history.undo());
        System.out.println("撤销后内容:" + editor.getContent());
        
        // 再次撤销
        editor.restoreFromMemento(history.undo());
        System.out.println("撤销两次后内容:" + editor.getContent());
    }
}

游戏存档系统

java
// 游戏状态
public class GameState {
    private int level;
    private int score;
    private String position;
    
    public GameState(int level, int score, String position) {
        this.level = level;
        this.score = score;
        this.position = position;
    }
    
    public int getLevel() {
        return level;
    }
    
    public int getScore() {
        return score;
    }
    
    public String getPosition() {
        return position;
    }
    
    @Override
    public String toString() {
        return "Level: " + level + ", Score: " + score + ", Position: " + position;
    }
}

// 备忘录:存储游戏状态
public class GameMemento {
    private final GameState state;
    
    public GameMemento(GameState state) {
        this.state = state;
    }
    
    public GameState getState() {
        return state;
    }
}

// 发起人:游戏
public class Game {
    private GameState currentState;
    
    public Game() {
        this.currentState = new GameState(1, 0, "起始点");
    }
    
    public void play(int scoreIncrease, String newPosition) {
        System.out.println("游戏进行中...");
        currentState = new GameState(
            currentState.getLevel(),
            currentState.getScore() + scoreIncrease,
            newPosition
        );
    }
    
    public void levelUp() {
        System.out.println("升级!");
        currentState = new GameState(
            currentState.getLevel() + 1,
            currentState.getScore(),
            currentState.getPosition()
        );
    }
    
    public GameState getState() {
        return currentState;
    }
    
    // 创建存档
    public GameMemento save() {
        return new GameMemento(currentState);
    }
    
    // 加载存档
    public void load(GameMemento memento) {
        this.currentState = memento.getState();
    }
}

// 管理者:存档管理器
public class SaveManager {
    private Map<String, GameMemento> saves = new HashMap<>();
    
    public void saveGame(String slot, GameMemento memento) {
        saves.put(slot, memento);
    }
    
    public GameMemento loadGame(String slot) {
        return saves.get(slot);
    }
}

// 使用示例
public class GameDemo {
    public static void main(String[] args) {
        Game game = new Game();
        SaveManager saveManager = new SaveManager();
        
        // 初始状态
        System.out.println("初始状态:" + game.getState());
        
        // 游戏进行
        game.play(100, "森林");
        game.levelUp();
        System.out.println("状态 1: " + game.getState());
        
        // 保存存档 1
        saveManager.saveGame("slot1", game.save());
        
        // 继续游戏
        game.play(200, "城堡");
        game.levelUp();
        System.out.println("状态 2: " + game.getState());
        
        // 保存存档 2
        saveManager.saveGame("slot2", game.save());
        
        // 加载存档 1
        game.load(saveManager.loadGame("slot1"));
        System.out.println("加载存档 1: " + game.getState());
        
        // 加载存档 2
        game.load(saveManager.loadGame("slot2"));
        System.out.println("加载存档 2: " + game.getState());
    }
}

优缺点

优点:

  1. 提供状态恢复机制
  2. 实现撤销操作
  3. 保持封装边界
  4. 简化发起人代码
  5. 支持历史快照
  6. 支持事务回滚

缺点:

  1. 消耗内存资源
  2. 管理器可能复杂
  3. 状态存储效率问题
  4. 可能暴露实现细节
  5. 增加系统复杂度

应用场景

  1. 文本编辑器撤销功能
  2. 游戏存档系统
  3. 数据库事务管理
  4. 软件配置管理
  5. 浏览器历史记录
  6. 工作流状态恢复
  7. 版本控制系统

与其他模式的关系

  • 与命令模式:配合实现撤销/重做
  • 与原型模式:备忘录可存储原型状态
  • 与状态模式:备忘录保存状态历史
  • 与迭代器模式:遍历历史状态
  • 与代理模式:保护备忘录访问
  • 与享元模式:共享历史状态

JDK 中的备忘录模式

  1. Java 序列化机制
  2. Java 事务 API(JTA)
  3. Java 对象持久化(JPA)
  4. Java Swing 撤销框架(UndoManager)
  5. Java Beans 持久化
  6. Spring 框架的事务管理
  7. Java 状态管理(javax.faces.component.StateHolder)

注意事项

  1. 状态存储策略(完整 vs 增量)
  2. 内存管理(清理旧状态)
  3. 状态序列化格式
  4. 安全考虑(加密敏感状态)
  5. 性能优化(懒加载状态)
  6. 支持深拷贝与浅拷贝
  7. 处理状态版本兼容

贡献者

The avatar of contributor named as LI SIR LI SIR
The avatar of contributor named as wkwbk wkwbk

页面历史