设计模式:022_备忘录模式

79 阅读2分钟

备忘录模式

备忘录模式(Memento),又叫快照模式。在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 主要用于捕获一个对象的内部状态,以便在将来的某个时候恢复此状态。

作用

  • 提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
  • 实现了内部状态的封装。除了创建它的发起人角色之外,其他对象都不能够访问这些状态信息。
  • 简化了发起人角色。发起人角色不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。

缺点

资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。

适用场景

  • 需要保存与恢复数据的场景,如玩游戏的存档功能。
  • 需要提供一个可回滚操作的场景,如 Word、记事本等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作。

类图

备忘录模式类图.png

  • 发起人角色(Originator):负责创建一个备忘录,记录自身需要保存的状态,而且需要具备状态的回滚功能。
  • 备忘录角色(Memento):用于存储 Originator 角色的内部状态,且可以防止 Originator 以外的对象进行访问。
  • 备忘录管理员角色(Caretaker):负责对备忘录进行管理,提供保存与获取备忘录的功能。且其本身不能对备忘录的内容进行访问与修改。

代码表达

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

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    // 保存状态
    public Memento saveStateMemento() {
        return new Memento(state);
    }

    // 恢复状态
    public void getStateFromMemento(Memento memento) {
        this.state = memento.getState();
    }
}
// 备忘录角色(Memento)
public class Memento {
    private String state;

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

    public String getState() {
        return state;
    }
}
// 备忘录管理员角色(Caretaker)
public class Caretaker {
    private List<Memento> mementoList = new ArrayList<>();

    public void add(Memento memento) {
        mementoList.add(memento);
    }

    public Memento get(int index) {
        if (index >= 0 && index < mementoList.size()) {
            return mementoList.get(index);
        }
        return null;
    }
}

客户端调用

Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
// 保存多个状态
originator.setState("state1:100");
caretaker.add(originator.saveStateMemento());
originator.setState("state2:200");
caretaker.add(originator.saveStateMemento());
originator.setState("state3:300");
caretaker.add(originator.saveStateMemento());
System.out.println(originator.getState());
// 恢复状态
originator.getStateFromMemento(caretaker.get(0));
System.out.println(originator.getState());
originator.getStateFromMemento(caretaker.get(1));
System.out.println(originator.getState());
originator.getStateFromMemento(caretaker.get(2));
System.out.println(originator.getState());