#
Momento
#
概念
备忘录模式(Memento Pattern)是一种行为型设计模式,主要用于在不破坏对象封装的前提下,捕获并保存对象的内部状态,以便之后可以将对象恢复到之前的状态。
常见的应用场景:
- 编辑器的撤销/恢复 (Undo/Redo)功能
- 游戏的存档/读档
- 事务操作的回滚
#
结构
备忘录模式通常包含三个角色:
- Originator(发起人/原发器)
- 负责创建一个备忘录,用于记录当前对象的状态。
- 也可以使用备忘录恢复状态。
- Memento(备忘录)
- 用来存储 Originator 的内部状态。
- 一般是只读的,不允许外部随意修改。
- Caretaker(管理者/负责人)
- 负责保存和恢复备忘录。
- 本身并不修改备忘录内容,只负责“看管”。
#
例子
// 备忘录
class Memento {
private final String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 发起人
class Originator {
private String state;
public void setState(String state) {
System.out.println("设置状态: " + state);
this.state = state;
}
public String getState() {
return state;
}
// 创建备忘录
public Memento saveStateToMemento() {
return new Memento(state);
}
// 从备忘录恢复状态
public void getStateFromMemento(Memento memento) {
this.state = memento.getState();
System.out.println("恢复状态: " + state);
}
}
// 管理者
class Caretaker {
private final java.util.Stack<Memento> mementoStack = new java.util.Stack<>();
public void add(Memento state) {
mementoStack.push(state);
}
public Memento undo() {
if (!mementoStack.isEmpty()) {
return mementoStack.pop();
}
return null;
}
}
// 测试类
public class MementoPatternDemo {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("状态 #1");
caretaker.add(originator.saveStateToMemento());
originator.setState("状态 #2");
caretaker.add(originator.saveStateToMemento());
originator.setState("状态 #3");
System.out.println("当前状态: " + originator.getState());
// 撤销操作
originator.getStateFromMemento(caretaker.undo());
originator.getStateFromMemento(caretaker.undo());
}
}
// 备忘录类:保存游戏状态
class GameMemento {
private final int level;
private final int hp;
public GameMemento(int level, int hp) {
this.level = level;
this.hp = hp;
}
public int getLevel() {
return level;
}
public int getHp() {
return hp;
}
}
// 发起人:游戏角色
class Game {
private int level;
private int hp;
public Game(int level, int hp) {
this.level = level;
this.hp = hp;
}
public void play() {
System.out.println("正在游戏... 当前等级: " + level + " 血量: " + hp);
level++;
hp -= 10; // 假设玩游戏会掉血
}
public void showState() {
System.out.println("当前角色 -> 等级: " + level + " 血量: " + hp);
}
// 存档
public GameMemento save() {
System.out.println("存档成功!等级: " + level + " 血量: " + hp);
return new GameMemento(level, hp);
}
// 读档
public void load(GameMemento memento) {
this.level = memento.getLevel();
this.hp = memento.getHp();
System.out.println("读档成功!恢复到 -> 等级: " + level + " 血量: " + hp);
}
}
// 管理者:存档管理器
class Caretaker {
private final java.util.Stack<GameMemento> saves = new java.util.Stack<>();
public void add(GameMemento memento) {
saves.push(memento);
}
public GameMemento undo() {
if (!saves.isEmpty()) {
return saves.pop();
}
return null;
}
}
// 测试类
public class GameMementoDemo {
public static void main(String[] args) {
Game game = new Game(1, 100);
Caretaker caretaker = new Caretaker();
game.showState();
caretaker.add(game.save()); // 存档 1
game.play();
caretaker.add(game.save()); // 存档 2
game.play();
game.play();
game.showState();
// 读档(回退到上一次存档)
game.load(caretaker.undo());
game.showState();
// 再次读档(回退到更早的存档)
game.load(caretaker.undo());
game.showState();
}
}
#
优点
- 可以实现对象状态的保存与恢复,支持撤销/回滚。
- 封装性好,状态存储在 Memento 中,不会暴露给外部。
#
缺点
- 可能会占用大量内存(特别是频繁保存时)。
- 如果对象状态过于复杂,保存和恢复的开销会比较大