设计模式——备忘录模式

备忘录模式(Memento Pattern)是一种行为型设计模式,它在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样可以在需要时将对象恢复到先前的状态。

原理

  • 发起人(Originator): 是拥有复杂内部状态的对象,它可以创建和恢复备忘录。
  • 备忘录(Memento): 存储发起人的内部状态,通常是一个值对象或数据容器,对外提供有限的接口以防止直接访问其内部细节。
  • 管理器/caretaker(Caretaker): 负责存储和传递备忘录对象,但不能对备忘录的内容进行操作或解读,只负责保管和还原发起人的状态。

Java代码示例

// 备忘录类
public class Memento {
    private final String state;

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

    // 只读方法,允许发起者获取备忘录中的状态
    public String getState() {
        return state;
    }
}

// 发起人(如游戏角色)
public class Originator {
    private String state;

    // 设置或获取当前状态
    public void setState(String state) {
        System.out.println("State changed to: " + state);
        this.state = state;
    }

    public String getState() {
        return state;
    }

    // 创建备忘录并保存当前状态
    public Memento saveToMemento() {
        return new Memento(state);
    }

    // 从备忘录恢复状态
    public void restoreFromMemento(Memento memento) {
        this.state = memento.getState();
        System.out.println("State restored to: " + state);
    }
}

// 管理器/caretaker
public class Caretaker {
    private Memento memento;

    public void setMemento(Memento memento) {
        this.memento = memento;
    }

    public Memento getMemento() {
        return memento;
    }
}

// 使用示例
public class Client {
    public static void main(String[] args) {
        Originator originator = new Originator();
        originator.setState("State A");

        // 保存当前状态到备忘录
        Caretaker caretaker = new Caretaker();
        caretaker.setMemento(originator.saveToMemento());

        // 改变状态
        originator.setState("State B");

        // 恢复之前保存的状态
        originator.restoreFromMemento(caretaker.getMemento());
    }
}

设想你正在玩一款电子游戏,每当你存档的时候,游戏就会把你的角色状态(等级、装备、位置等)打包成一个“备忘录”,然后存入存档文件中。当你想要读取存档时,游戏会从存档文件中取出“备忘录”,并将角色状态恢复到存档时的样子。在这个过程中,游戏程序(发起人)通过备忘录模式保护了内部状态信息,而存档系统(管理器)仅负责保存和加载这些备忘录。

应用场景

  • 文本编辑器:用户可以随时保存文档状态(备忘录),并在需要时撤销到之前的状态。
  • 游戏:保存和恢复玩家的游戏进度或角色属性状态。
  • 数据库事务:事务管理器使用备忘录保存事务开始时的数据状态,在事务失败时能够回滚到初始状态。

适用性

  • 需要保存和恢复对象的内部状态到过去某个时刻的情况。
  • 对象的状态信息应该作为值对象来存储,而不是通过复制对象的所有变量。
  • 当直接访问对象内部状态违反封装原则或者可能导致对象状态不一致时。

你可能感兴趣的:(Java,系列文章,设计模式,备忘录模式,java)