定义
备忘录模式(Memento Pattern)又称为快照(Snapshot)模式或Token模式。
英文原话:Without violating encapsulation,capture and externalize an object's internal state so that the object can be restored to this state later.
翻译:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将对象恢复到原先保存的状态。
通俗地说,备忘录模式就是提供一种程序数据的备份方法将一个对象进行备份。
角色
发起人(Originator)角色:该角色记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘数据。
备忘录(Memento)角色:该角色负责存储发起人角色的内部状态,在必要时提供发起人需要的内部状态数据。
负责人(Caretaker)角色:该角色对备忘录角色进行管理、保存以及提供备忘录。
/** * 发起人角色 */ public class Originator { private String state = null; //创建备忘录 public Memento createMemento(){ return new Memento(this.state); } //恢复一个备忘录 public void restoreMemento(Memento memento){ this.setState(memento.getState()); } public String getState() { return state; } public void setState(String state) { this.state = state; } } /** * 备忘录角色 */ public class Memento { //发起人内部状态 private String state; //构造函数传递参数 public Memento(String state) { this.state = state; } public String getState() { return state; } public void setState(String state) { this.state = state; } } /** * 负责人角色 */ public class Caretaker { //备忘录角色 private Memento memento; public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; } } /** * 测试类 */ public class Client { public static void main(String[] args) { Originator org = new Originator(); //定义负责人 Caretaker caretaker = new Caretaker(); System.out.println("初始值:"+org.getState()); //创建一个备忘录 caretaker.setMemento(org.createMemento()); org.setState("改变初始值"); System.out.println("改变后:"+org.getState()); //恢复备忘录 org.restoreMemento(caretaker.getMemento()); System.out.println("恢复后的值:"+org.getState()); } }
应用场景
- 需要保存和恢复数据的相关状态场景。
- 提供一个可回滚的操作。
- 需要监控副本的场景中。
- 数据库连接的事务管理使用的就是备忘录模式。
注意事项
- 备忘录的生命周期。备忘录创建出来就要在最近的代码中使用,系统主动管理它的生命周期,建立就要使用,不使用就要立刻删除其引用,等待垃圾回收器对它的回收处理。
- 备忘录的性能。不要在频繁建立备份的场景中使用备忘录模式。(例如:for循环语句中,原因有两点。一是不能控制备忘录建立的对象数量;二是大对象的建立要消耗大量资源,系统的性能需要重新考虑。因此,如果出现这样的代码,设计师应该修改架构)。
/** * 发起人角色 */ public class GamePlayer { private String name; //角色名 private int hp; //血量 private int mp; //魔法 private int level; //等级 public GamePlayerBackup createBackup(){ return new GamePlayerBackup(this.name,this.hp,this.mp,this.level); } public void restoreGamePlayer(GamePlayerBackup gpBackup){ this.setHp(gpBackup.getHp()); this.setMp(gpBackup.getMp()); this.setName(gpBackup.getName()); this.setLevel(gpBackup.getLevel()); } public void KillBoss(){ System.out.println(this.name+"开始打BOSS"); while(this.hp>0){ //如果没挂就继续打 System.out.println(this.name+"使用技能攻击,消耗30MP.MP剩余:"+(this.mp-=30)); System.out.println("Boss攻击"+this.name+"HP减50.HP剩余:"+(this.hp-=50)); System.out.println(this.toString()); if (this.hp<=0){ System.out.println("游戏角色"+this.name+"被Boss击杀!"); } } } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getHp() { return hp; } public void setHp(int hp) { this.hp = hp; } public int getMp() { return mp; } public void setMp(int mp) { this.mp = mp; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public GamePlayer(String name, int hp, int mp, int level) { this.name = name; this.hp = hp; this.mp = mp; this.level = level; } @Override public String toString() { return "游戏角色{" + "角色名='" + name + '\'' + ", 血量=" + hp + ", 法力值=" + mp + ", 等级=" + level + '}'; } } /** * 备忘录对象 */ public class GamePlayerBackup { private String name; //角色名 private int hp; //血量 private int mp; //魔法 private int level; //等级 public GamePlayerBackup(String name, int hp, int mp, int level) { this.name = name; this.hp = hp; this.mp = mp; this.level = level; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getHp() { return hp; } public void setHp(int hp) { this.hp = hp; } public int getMp() { return mp; } public void setMp(int mp) { this.mp = mp; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } } /** * 负责人角色 */ public class CareTaker { GamePlayerBackup gpBackup; public GamePlayerBackup getGpBackup() { return gpBackup; } public void setGpBackup(GamePlayerBackup gpBackup) { this.gpBackup = gpBackup; } } public class Main { public static void main(String[] args) { GamePlayer gamePlayer = new GamePlayer("李逍遥",500,500,20); //发起人角色 System.out.println("初始状态"+gamePlayer.toString()); CareTaker caretaker = new CareTaker(); //负责人角色 caretaker.setGpBackup(gamePlayer.createBackup()); //发起人创建备忘录角色并传给负责人保管 gamePlayer.KillBoss(); //打怪 //恢复备忘录角色 gamePlayer.restoreGamePlayer(caretaker.getGpBackup()); System.out.println("--------游戏角色复活--------"+gamePlayer.toString()); } }