Skip to content

备忘录模式

字数: 0 字 时长: 0 分钟

简介

备忘录模式(Memento Pattern)核心思想是:在不破坏对象封装性的前提下,捕获一个对象的内部状态,并在将来需要的时候能恢复这个状态。优点是支持撤销和回退操作,封装性强;缺点是内存开销大、恢复状态时有限制,不支持更灵活的版本控制。

UML 类图

memento.webp

  • 发起人(Originator):需要保存状态的对象,负责创建和恢复备忘录
  • 备忘录(Memento):存储发起人的内部状态,是一个纯数据对象
  • 管理者(Caretaker):负责保存备忘录对象,但不直接操作备忘录的内容

实现示例

以“文档编辑器撤销/重做”为例:

java
// 1. 创建备忘录对象
class DocumentMemento {
    private String content;
    public DocumentMemento(String content) {
        this.content = content;
    }
    // 只提供读取功能,确保封装性
    public String getContent() {
        return content;
    }
}

// 2. 创建发起人(要保存状态的文档)
class Document {
    @Getter
    @Setter
    private String content;
    public Document(String content) {
        this.content = content;
    }
    public DocumentMemento save() {
        return new DocumentMemento(this.content); // 备份
    }
    public void restore(DocumentMemento memento) {
        this.content = memento.getContent(); // 重做
    }
}

// 3. 创建管理者 (负责保存多个状态,用于撤销和重做)
class History {
    private Stack<DocumentMemento> history = new Stack<>();
    private Stack<DocumentMemento> redoStack = new Stack<>();
    public void pushMemento(DocumentMemento memento) {
        history.push(memento);
        redoStack.clear(); // 每次新操作时清空重做栈
    }
    public DocumentMemento popMemento() {
        if (!history.isEmpty()) {
            DocumentMemento memento = history.pop();
            redoStack.push(memento);
            return memento;
        }
        return null;
    }
    public DoccumentMemento popRedoMemento() {
        if (!redoStack.isEmpty()) {
            DocumentMemento memento = redoStack.pop();
            history.push(memento);
            return memento;
        }
        return null;
    }
}

// 4. 调用示例
public static void main(String[] args) {
    Document document = new Document("初始内容");
    History history = new History();
    // 保存初始状态
    history.pushMemento(document.save());
    // 修改文档内容,保存状态
    document.setContent("第一次修改后的内容");
    history.pushMemento(document.save());
    // 第二次修改
    document.setContent("第二次修改后的内容");
    history.pushMemento(document.save());
    // 撤销 (回到第一次修改后的状态)
    document.restore(history.popMemento());
    // 再次撤销 (回到初始状态)
    document.restore(history.popMemento());
    // 重做 (回到第一次修改后的状态)
    document.restore(history.popRedoMemento());
}