备忘录模式(Memento)

273

备忘录模式(Memento)

Memento:备忘录模式是一种行为设计模式,允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。

/**
 * 备忘录模式
 *
 * @author CAI
 * @time 2020/11/12
 */
public class MementoPattern {

    public static void main(String[] args) {
       FileCaretaker caretaker = new FileCaretaker();

       FileWriter writer = new FileWriter("data.txt");
       writer.write("First Set of Data \n");
       System.out.println(writer);

       caretaker.save(writer);
       writer.write("Second Set of Data \n");
       System.out.println(writer);

       caretaker.undo(writer);
       System.out.println(writer);
    }
}

/**
 * 文件助手(发起者类)
 */
class FileWriter {

    /**
     * 文件名
     */
    private String fileName;

    /**
     * 内容
     */
    private StringBuilder content;

    public FileWriter(String fileName) {
        this.fileName = fileName;
        this.content = new StringBuilder();
    }

    /**
     * 写入
     *
     * @param string 字符串
     */
    public void write(String string) {
        content.append(string);
    }

    /**
     * 保存
     *
     * @return 备忘录
     */
    public Memento save() {
        return new Memento(this.fileName, this.content);
    }

    /**
     * 撤销最后一次保存
     *
     * @param memento 备忘录
     */
    public void undoToLastSave(Memento memento) {
        this.fileName = memento.getFileName();
        this.content = memento.getContent();
    }

    @Override
    public String toString() {
        return content.toString();
    }
}

/**
 * 备忘录类
 */
class Memento {

    /**
     * 文件名
     */
    private final String fileName;

    /**
     * 内容
     */
    private final StringBuilder content;

    public Memento(String fileName, StringBuilder content) {
        this.fileName = fileName;
        this.content = new StringBuilder(content);
    }

    public String getFileName() {
        return fileName;
    }

    public StringBuilder getContent() {
        return content;
    }
}

/**
 * 管理者类
 */
class FileCaretaker {

    /**
     * 备忘录
     */
    private Memento memento;

    public void save(FileWriter writer) {
        this.memento = writer.save();
    }

    public void undo(FileWriter writer) {
        writer.undoToLastSave(memento);
    }
}
  1. Originator(发起人:FileWriter)类:负责创建一个Memento,用以记录当前的内部状态,并可以使用备忘录恢复内部状态。
    • Originator可根据需要,决定Memento存储Originator的哪些内部状态。
  2. Memento(备忘录)类:负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento
    • Memento通常有两个接口:
      1. Caretaker只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。
      2. Originator能够看到一个宽接口,允许它访问返回先前状态所需的所有数据。
  3. Caretaker(管理者:FileCaretaker)类:负责保存好Memento,不能对Memento的内容进行操作或检查。

应用场景

  1. 当某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的状态。
    • 备忘录模式允许你复制对象中的全部状态 (包括私有的成员变量),并将其独立于对象进行保存。
  2. 系统中需要维护或记录属性历史的类,可以使用备忘录模式。

优缺点

  • 优点:
    • 可以在不破坏对象封装情况的前提下创建对象状态快照。
    • 对象的已保存状态数据在对象外部不可访问,这保护了已保存状态数据的完整性。
  • 缺点:
    • 若客户端频繁的创建备忘录对象,程序会消耗大量的内存。
    • 负责人必须完整的跟踪发起人的生命周期,这样才能即使销毁已经弃用的备忘录对象。

在 Java 中的应用

Java核心库为例:

  • java.io.Serializable:的实现。