备忘录模式 模式引入 问题描述 如果我们玩过 RPG 游戏,就知道在关键时点需要进行存档,否则一不小心就可能给出「大侠,请重新来过」的提示,这就需要有一个存档功能。考虑最简单的实现,直接用一个队列或字典将对应时点的状态存起来就行了,当需要恢复某个历史状态时,将对应的状态取出,更新到当前状态。但是这个「保存」和「恢复」在写程序时会有一些问题,大部分的面向对象语言都不允许对私有成员进行外部访问,这有益于程序的健壮。 模式定义 像刚刚这种情况,当公共接口无法从外部获取一个对象的内部状态,但我们又需要访问和处理它的内部状态,此时可以使用备忘录模式。 备忘录模式(Memento)是在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将该对象恢复到原先保存的状态。
如果我们玩过 RPG 游戏,就知道在关键时点需要进行存档,否则一不小心就可能给出「大侠,请重新来过」的提示,这就需要有一个存档功能。考虑最简单的实现,直接用一个队列或字典将对应时点的状态存起来就行了,当需要恢复某个历史状态时,将对应的状态取出,更新到当前状态。但是这个「保存」和「恢复」在写程序时会有一些问题,大部分的面向对象语言都不允许对私有成员进行外部访问,这有益于程序的健壮。
像刚刚这种情况,当公共接口无法从外部获取一个对象的内部状态,但我们又需要访问和处理它的内部状态,此时可以使用备忘录模式。
备忘录模式(Memento)是在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将该对象恢复到原先保存的状态。
让我们用备忘录模式实现问题中的存档,备忘录(存档)用来存储游戏进行到某个时间点的角色状态。当保存状态时,玩家发起一个备忘角色当前时间点的状态到备忘录(存档);恢复状态时,将该时间点的备忘录(存档)恢复到游戏。
GameRole,并定义角色方法。当然,最主要要的是保存状态 saveState 和恢复状态 recoveryState 方法。RoleStateMemento,里面存有角色在存档时间点的所有状态。RoleStateCaretaker,用来设置或获取对应的存档。Originator 类:
public class GameRole { // 生命力 private int vit; // 攻击力 private int atk; // 防御力 private int def; public int getVit() { return vit; } public void setVit(int vit) { this.vit = vit; } public int getAtk() { return atk; } public void setAtk(int atk) { this.atk = atk; } public int getDef() { return def; } public void setDef(int def) { this.def = def; } // 状态显示 public void stateDisplay() { System.out.println("当前角色状态:"); System.out.println("体力:" + this.vit); System.out.println("攻击力:" + this.atk); System.out.println("防御力:" + this.def); System.out.println(); } // 获得初始状态 public void getInitState() { this.vit = 100; this.atk = 100; this.def = 100; } // 战斗 public void fight() { this.vit = 0; this.atk = 0; this.def = 0; } // 保存游戏状态 public RoleStateMemento saveState() { return new RoleStateMemento(vit, atk, def); } // 恢复角色状态 public void recoveryState(RoleStateMemento memento) { this.vit = memento.getVit(); this.atk = memento.getAtk(); this.def = memento.getDef(); } }
Memento 类:
public class RoleStateMemento { private int vit; private int atk; private int def; public int getVit() { return vit; } public void setVit(int vit) { this.vit = vit; } public int getAtk() { return atk; } public void setAtk(int atk) { this.atk = atk; } public int getDef() { return def; } public void setDef(int def) { this.def = def; } public RoleStateMemento(int vit, int atk, int def) { this.vit = vit; this.atk = atk; this.def = def; } public RoleStateMemento() {} }
Careataker 类:
public class RoleStateCaretaker { private RoleStateMemento memento; public RoleStateMemento getMemento() { return memento; } public void setMemento(RoleStateMemento memento) { this.memento = memento; } }
Main 方法:
public class Main { public static void main(String[] args) { // 大战Boss前 GameRole lixiaoyao = new GameRole(); lixiaoyao.getInitState(); lixiaoyao.stateDisplay(); // 保存进度 RoleStateCaretaker stateAdmin = new RoleStateCaretaker(); stateAdmin.setMemento(lixiaoyao.saveState()); // 大战Boss时,损耗严重 lixiaoyao.fight(); lixiaoyao.stateDisplay(); // 恢复之前状态 lixiaoyao.recoveryState(stateAdmin.getMemento()); lixiaoyao.stateDisplay(); } }
执行结果:
当前角色状态: 体力:100 攻击力:100 防御力:100 当前角色状态: 体力:0 攻击力:0 防御力:0 当前角色状态: 体力:100 攻击力:100 防御力:100

备忘录模式优点包括:
备忘录模式缺点包括: