一、什么是备忘录模式备忘录这个词汇大家应该都不陌生,我就经常使用备忘录来记录一些比较重要的或者容易遗忘的信息,与之相关的最常见的应用有许多,比如游戏存档,我们玩游戏的时候肯定有存档功能,旨在下一次登录游戏时可以从上次退出的地方继续游戏,或者对复活点进行存档,如果挂掉了则可以读取复活点的存档信息重新开始。与之相类似的就是数据库的事务回滚,或者重做日志redo log等。 备忘录模式(Memento),在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存着这个状态。这样以后就可将该对象恢复到原先保存的状态。UML结构图如下: 其中,Originator是发起人,负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态;Memento是备忘录,负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento;Caretaker是管理者,负责保存好备忘录的Memento,不能对备忘录的内容进行操作或检查。 1. 发起人角色记录当前时刻的内部状态,并负责创建和恢复备忘录数据,允许访问返回到先前状态所需的所有数据。 1 public class Originator { 2 3 private String state; 4 5 public String getState() { 6 return state; 7 } 8 9 public void setState(String state) {10 this.state = state;11 }12 13 public Memento createMento() {14 return (new Memento(state));15 }16 17 public void setMemento(Memento memento) {18 state = memento.getState();19 }20 21 public void show() {22 System.out.println("state = " + state);23 }24 25 } 2. 备忘录角色负责存储Originator发起人对象的内部状态,在需要的时候提供发起人需要的内部状态。 1 public class Memento { 2 3 private String state; 4 5 public Memento(String state) { 6 this.state = state; 7 } 8 9 public String getState() {10 return state;11 }12 13 } 3. 备忘录管理员角色对备忘录进行管理、保存和提供备忘录,只能将备忘录传递给其他角色。 1 public class Caretaker { 2 3 private Memento memento; 4 5 public Memento getMemento() { 6 return memento; 7 } 8 9 public void setMemento(Memento memento) {10 this.memento = memento;11 }12 13 } 4. Client客户端下面编写一小段代码测试一下,即先将状态置为On,保存后再将状态置为Off,然后通过备忘录管理员角色恢复初始状态。 1 public class Client { 2 3 public static void main(String[] args) { 4 Originator originator = new Originator(); 5 originator.setState("On"); //Originator初始状态 6 originator.show(); 7 8 Caretaker caretaker = new Caretaker(); 9 caretaker.setMemento(originator.createMento());10 11 originator.setState("Off"); //Originator状态变为Off12 originator.show();13 14 originator.setMemento(caretaker.getMemento()); //回复初始状态15 originator.show();16 }17 18 } 运行结果如下: 二、备忘录模式的应用1. 何时使用
2. 方法
3. 优点
4. 缺点
5. 使用场景
6. 应用实例
7. 注意事项
三、备忘录模式的实现下面以游戏存档为例,看一下如何用备忘录模式实现。UML图如下: 1. 游戏角色简单记录了游戏角色的生命力、攻击力、防御力,通过saveState()方法来保存当前状态,通过recoveryState()方法来恢复角色状态。 1 public class GameRole { 2 3 private int vit; //生命力 4 private int atk; //攻击力 5 private int def; //防御力 6 7 public int getVit() { 8 return vit; 9 }10 public void setVit(int vit) {11 this.vit = vit;12 }13 public int getAtk() {14 return atk;15 }16 public void setAtk(int atk) {17 this.atk = atk;18 }19 public int getDef() {20 return def;21 }22 public void setDef(int def) {23 this.def = def;24 }25 26 //状态显示27 public void stateDisplay() {28 System.out.println("角色当前状态:");29 System.out.println("体力:" + this.vit);30 System.out.println("攻击力:" + this.atk);31 System.out.println("防御力: " + this.def);32 System.out.println("-----------------");33 }34 35 //获得初始状态36 public void getInitState() {37 this.vit = 100;38 this.atk = 100;39 this.def = 100;40 }41 42 //战斗后43 public void fight() {44 this.vit = 0;45 this.atk = 0;46 this.def = 0;47 }48 49 //保存角色状态50 public RoleStateMemento saveState() {51 return (new RoleStateMemento(vit, atk, def));52 }53 54 //恢复角色状态55 public void recoveryState(RoleStateMemento memento) {56 this.vit = memento.getVit();57 this.atk = memento.getAtk();58 this.def = memento.getDef();59 }60 61 } 2. 角色状态存储箱备忘录类,用于存储角色状态。 1 public class RoleStateMemento { 2 3 private int vit; //生命力 4 private int atk; //攻击力 5 private int def; //防御力 6 7 public RoleStateMemento(int vit, int atk, int def) { 8 this.vit = vit; 9 this.atk = atk;10 this.def = def;11 }12 13 public int getVit() {14 return vit;15 }16 17 public void setVit(int vit) {18 this.vit = vit;19 }20 21 public int getAtk() {22 return atk;23 }24 25 public void setAtk(int atk) {26 this.atk = atk;27 }28 29 public int getDef() {30 return def;31 }32 33 public void setDef(int def) {34 this.def = def;35 }36 37 } 3. 角色状态管理者备忘录管理者。 1 public class RoleStateCaretaker { 2 3 private RoleStateMemento memento; 4 5 public RoleStateMemento getMemento() { 6 return memento; 7 } 8 9 public void setMemento(RoleStateMemento memento) {10 this.memento = memento;11 }12 13 } 4. Client客户端下面编写一个简单的程序测试一下,编写逻辑大致为打boss前存档,打boss失败了,读档。 1 public class Client { 2 3 public static void main(String[] args) { 4 //打boss前 5 GameRole gameRole = new GameRole(); 6 gameRole.getInitState(); 7 gameRole.stateDisplay(); 8 9 //保存进度10 RoleStateCaretaker caretaker = new RoleStateCaretaker();11 caretaker.setMemento(gameRole.saveState());12 13 //打boss失败14 gameRole.fight();15 gameRole.stateDisplay();16 17 //恢复状态18 gameRole.recoveryState(caretaker.getMemento());19 gameRole.stateDisplay();20 }21 22 } 运行结果如下: |
|