设计模式-备忘录模式

71 阅读2分钟

一、备忘录模式介绍

备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。该模式又叫快照模式。

备忘录模式角色:

  • 发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
  • 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
  • 管理者/守护者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

此处我们有一个诉求:

  • 使用备忘录模式完成游戏中的血量恢复。

二、备忘录模式使用

2.1 示例关系:

2.2 代码实现:

/* *
 * 1. 备忘录类(Memento)。
 */

class Memento {

    /* *
     * 血量。
     */

    private String HP;

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

    public String getHP() {
        return HP;
    }

}



/* *
 * 2. 发起者类(Originator)。
 */

class Originator {

    private String HP;

    public String getHP() {
        return HP;
    }

    public void setHP(String HP) {
        this.HP = HP;
    }

    /* *
     * 创建备忘(创建,并将当前发起者的HP值赋给备忘录对象)。
     */

    public Memento createMemento() {
        return new Memento(this.HP);
    }

    /* *
     * 恢复备忘(将备忘录对象的HP值赋给当前发起者对象)。
     */

    public void restoreMemento(Memento memento) {
        this.setHP(memento.getHP());
    }
}



/* *
 * 3. 守护者类(Caretaker)。
 */

class Caretaker {

    /* *
     * 可保存多次状态的备忘集。
     * 若需要对不同角色保存多个状态可以使用Map方式。
     */

    List<Memento> mementos;

    /* *
     * 构造。
     */

    public Caretaker() {
        mementos = new ArrayList<>();
    }

    /* *
     * 添加备忘录对象。
     */

    public void addMemento(Memento memento) {
        if (!mementos.contains(memento)) {
            mementos.add(memento);
        }
    }

    /* *
     * 获取备忘录对象。
     */

    public Memento getMemento(int index) {
        return mementos.get(index);
    }
}



/* *
 * 4. 客户端调用。
 */

public class Client {

    public static void main(String[] args) {

        // 创建发起者与守护者。
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();


        // 初始状态。
        originator.setHP("HP 100%");
        System.out.println("初始状态为:" + originator.getHP());

        // 保存状态。(创建备忘录对象并添加至守护者备忘集中)
        caretaker.addMemento(originator.createMemento());

        // 设置新状态。
        originator.setHP("HP 60%");
        System.out.println("受伤后状态:" + originator.getHP());

        // 恢复状态。
        Memento memento = caretaker.getMemento(0);
        originator.restoreMemento(memento);
        System.out.println("恢复后状态:" + originator.getHP());

        // 初始状态为:HP 100%
        // 受伤后状态:HP 60%
        // 恢复后状态:HP 100%
    }

}

三、备忘录模式总结

优点

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

缺点

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

应用场景

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

四、结束语

“-------怕什么真理无穷,进一寸有一寸的欢喜。”

微信公众号搜索:饺子泡牛奶