定义
备忘录(Memento):在不破化封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个对象。这样以后就可以将该对象恢复到原先保存的状态。
我们都知道,软件的运行,本质上就是数据的查询、运算、展示。当软件运行到某个时期,我们只需要,吧他各个属性和值保存一下,然后不管什么时候,制药再赋值回去,就能让软件进入备份时的状态。
UML类图
角色职责
- originator:对象(需要保存状态的对象)
- Memento:备忘录对象,负责保存好记录,即Originator内部状态
- Caretaker:守护者对象,负责保存多个备忘录对象,使用集合管理,提高效率
- 说明:如果希望保存多个originator对象的不同时间的状态,也可以,只需要要HashMap<String,集合>
案例
模拟游戏通过关卡后,自动进行存档。
案例UML类图
代码
Game
// 需要保存的对象
public class Game {
private int roleLevel;
private int gameLevel;
/**
* 存档</br>
* 创建 Memento,并将当前的状态存入 Memento
* @return 备份当前状态的 Memento 对象
*/
public Memento createMemento() {
System.out.println("存档完毕");
return new Memento(roleLevel,gameLevel);
}
/**
* 根据传入的存档对象,恢复游戏数据</br>
* 将传入的Memento对象的数据赋值到当前对象
* @param memento 想恢复到的档案
*/
public void recoverGameFromMemento(Memento memento) {
roleLevel = memento.getRoleLevel();
gameLevel = memento.getGameLevel();
}
public void display() {
System.out.println("角色等级:"+roleLevel
+ " 游戏关卡:"+gameLevel);
}
public int getRoleLevel() {
return roleLevel;
}
public void setRoleLevel(int roleLevel) {
this.roleLevel = roleLevel;
}
public int getGameLevel() {
return gameLevel;
}
public void setGameLevel(int gameLevel) {
this.gameLevel = gameLevel;
}
}
Memento
public class Memento {
private int roleLevel;
private int gameLevel;
public Memento(int roleLevel, int gameLevel) {
super();
this.roleLevel = roleLevel;
this.gameLevel = gameLevel;
}
public int getRoleLevel() {
return roleLevel;
}
public void setRoleLevel(int roleLevel) {
this.roleLevel = roleLevel;
}
public int getGameLevel() {
return gameLevel;
}
public void setGameLevel(int gameLevel) {
this.gameLevel = gameLevel;
}
}
Caretaker
import java.util.List;
import java.util.Map;
public class Caretaker {
// 一个角色,一个存档
private Memento memento;
// // 一个角色,多个存档
// private List<Memento> mementos;
// // 多个角色,多个存档
// private Map<String , List<Memento>> gamesMementos;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
Client
public class Client {
public static void main(String[] args) {
// 创建游戏对象
Game game = new Game();
System.out.println("肝了一夜后");
game.setRoleLevel(15);
game.setGameLevel(2);
game.display();
System.out.println("赶紧存个档");
Caretaker caretaker = new Caretaker();
caretaker.setMemento(game.createMemento());
System.out.println("继续肝");
game.setRoleLevel(18);
game.setGameLevel(2);
game.display();
System.out.println("不小心死了,从存档里边恢复");
game.recoverGameFromMemento(caretaker.getMemento());
game.display();
System.out.println("继续肝");
game.setRoleLevel(21);
game.setGameLevel(2);
game.display();
System.out.println("通过了第三关,赶紧存档(覆盖之前存档)");
caretaker.setMemento(game.createMemento());
}
}
运行结果:
肝了一夜后
角色等级:15 游戏关卡:2
赶紧存个档
存档完毕
继续肝
角色等级:18 游戏关卡:2
不小心死了,从存档里边恢复
角色等级:15 游戏关卡:2
继续肝
角色等级:21 游戏关卡:2
通过了第三关,赶紧存档(覆盖之前存档)
存档完毕
优缺点
优点
- 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
- 实现了信息的封装,使得用户不需要关心状态的保存细节。
缺点
消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
应用场景
- 需要保存/恢复数据的相关状态场景。
- 提供一个可回滚的操作。