# 备忘录模式(Memento Pattern)

目录: https://note.dolyw.com/design/ (opens new window)

代码地址

# 1. 介绍

备忘录模式保存一个对象的某个状态,以便在适当的时候恢复对象,就类似游戏的存档。备忘录模式属于行为型模式

# 1.1. 特点

待补充

# 1.2. 结构

  • 原发器类(Originator):创建一个备忘录对象,使用备忘录存储它的内部状态
  • 备忘录类(Memento):将原发器的内部状态存储起来,原发器根据需要决定备忘录存储原发器的哪些内部状态
  • 负责人类(CareTaker):负责保存好备忘录对象,不能检查或操作备忘录的内容

# 1.3. 优缺点

  • 意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态
  • 主要解决:所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态
  • 何时使用:很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃
  • 如何解决:通过一个备忘录类专门存储对象状态
  • 关键代码:客户不与备忘录类耦合,与备忘录管理类耦合
  • 使用场景:需要保存/恢复数据的相关状态场景。提供一个可回滚的操作
  • 优点:
    • 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态
    • 实现了信息的封装,使得用户不需要关心状态的保存细节
  • 缺点:
    • 如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存或存储空间
  • 应用实例:
    • 后悔药
    • 打游戏时的存档
    • 浏览器中的历史记录
  • 注意事项:
    • 为了符合迪米特原则,还要增加一个管理备忘录的类
    • 为了节约内存,可使用原型模式+备忘录模式

# 2. 代码

模拟游戏存档的小例子

/**
 * 当前游戏状态
 *
 * @author wliduo[i@dolyw.com]
 * @date 2023/2/2 10:45
 */
public class GameOriginator {

    private String state;

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

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

    public String getState(){
        return state;
    }

    public GameMemento saveMemento(){
        return new GameMemento(state);
    }

    public void getFromMemento(GameMemento gameMemento){
        state = gameMemento.getState();
    }
}
/**
 * 游戏记录
 *
 * @author wliduo[i@dolyw.com]
 * @date 2023/2/2 10:45
 */
public class GameMemento {

    private String state;

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

    public String getState(){
        return state;
    }
}
/**
 * 游戏记录管理
 *
 * @author wliduo[i@dolyw.com]
 * @date 2023/2/2 10:45
 */
public class GameCareTaker {

    private List<GameMemento> gameMementoList = new ArrayList<>();

    public void add(GameMemento gameMemento){
        gameMementoList.add(gameMemento);
    }

    public GameMemento get(int index){
        return gameMementoList.get(index);
    }
}
/**
 * 备忘录模式 - 游戏存档,浏览器历史记录
 *
 * @author wliduo[i@dolyw.com]
 * @date 2023/2/2 10:45
 */
public class Main {

    public static void main(String[] args) {
        GameCareTaker gameCareTaker = new GameCareTaker();
        // 开始游戏
        GameOriginator gameOriginator = new GameOriginator("1# 你出生了,你正在新手村出生位置");
        System.out.println(gameOriginator.getState());
        // 游戏存档
        gameCareTaker.add(gameOriginator.saveMemento());
        gameOriginator.setState("2# 去找村长对话");
        System.out.println(gameOriginator.getState());
        // 游戏存档
        gameCareTaker.add(gameOriginator.saveMemento());
        gameOriginator.setState("3# 获得任务,杀死史莱姆");
        System.out.println(gameOriginator.getState());
        // 游戏读取存档
        gameOriginator.getFromMemento(gameCareTaker.get(1));
        System.out.println(gameOriginator.getState());
        // 游戏读取存档
        gameOriginator.getFromMemento(gameCareTaker.get(0));
        System.out.println(gameOriginator.getState());
    }
}
1# 你出生了,你正在新手村出生位置
2# 去找村长对话
3# 获得任务,杀死史莱姆
2# 去找村长对话
1# 你出生了,你正在新手村出生位置
上次更新时间: 2023-12-15 03:14:55