备忘录模式
备忘录模式 Memento 概述
什么是备忘录模式
提供一种状态恢复机制,可以保存某个历史时刻的状态,并且状态可以方便的恢复到某个特定的历史时刻,例如数据备份与还原,编辑与撤销,虚拟机生成快照,与根据快照进行恢复
在不破坏封装性的前提下,捕获对象的内部状态,并在该对象之外保存这个状态后续将该对象恢复到原先保存的状态
备忘录模式角色分析
- 原发器 Originator : 需要保存的原始数据对象类,可以存储她的内部状态为备忘录,使用备忘录恢复它的内部状态
- 备忘录 Memento : 存储原发器的内部状态,根据原发器来决定保存哪些内部状态,除了原发器与负责人以外,备忘录不允许被其它类直接使用,
- 负责人 Caretaker : 又称为管理者,持有备忘录容器,将原发器的指定保存创建的备忘录存储到负责人持有的容器中,只负责存储,而不能修改对象,无需知道对象的实现细节
备忘录模式示例
案例代码
游戏角色状态记录,创建游戏角色,该有角色有攻击力,防御力状态,记录较色状态,角色大战后恢复角色状
- 创建游戏角色类(原发器)
class GameRole{
public String id;
public int vit;//攻击力
public int def;//防御力
public GameRole(String id, int vit, int def) {
this.id = id;
this.vit = vit;
this.def = def;
}
//获取当前游戏角色状态
public Memento getMemento(GameRole gameRole) {
return new Memento(gameRole.id,gameRole.vit, gameRole.def);
}
//显示当前状态
public void descState() {
System.out.println("当前状态: 攻击力:"+this.vit+",防御力:"+this.def);
}
//大战,将当前游戏攻击力设置为50,防御力设置为50
public void fighting() {
this.vit = 50;
this.def = 50;
}
//恢复到某个状态Memento
public void restore(Memento memento) {
this.vit = memento.vit;
this.def = memento.def;
}
}
- 创建状态类(备忘录),复制游戏角色状态数据
class Memento{
public String id;
public int vit;//攻击力
public int def;//防御能力
public Memento(String id, int vit, int def) {
this.id = id;
this.vit = vit;
this.def = def;
}
}
- 创建管理者(负责人)
class Caretaker{
//记录各种状态 String为指定对象的id,List为该对象在某个时刻的状态
public Map<String,List<Memento>> recordMap = new HashMap<>();
//对游戏的某个节点的状态进行存储
public void saveMemento(Memento memento) {
List<Memento> mementoList = recordMap.get(memento.id);
if(null == mementoList) {
mementoList = new ArrayList<Memento>();
}
mementoList.add(memento);
recordMap.put(memento.id, mementoList);
}
//根据游戏id,获取某个阶段index,的状态
public Memento getStartMemento(String id, int index) {
List<Memento> mementoList = recordMap.get(id);
if(null == mementoList || mementoList.size()<index) {
System.out.println("没有该状态记录");
return null;
}
return mementoList.get(index-1);
}
}
- 调用测试
public static void main(String[]args) {
//创建管理者
Caretaker caretaker = new Caretaker();
//创建游戏角色对象
GameRole gameRole = new GameRole("111",80,80);
//显示当前角色信息
gameRole.descState();
//获取当前角色的备忘录
Memento memento= gameRole.getMemento(gameRole);
//存储备忘录
caretaker.saveMemento(memento);
//游戏角色开始大战
gameRole.fighting();
//显示大战后的角色信息
gameRole.descState();
//根据角色id,获取时刻为1的备忘录
Memento startMemento = caretaker.getStartMemento(gameRole.id, 1);
//将角色状态恢复到备忘录状态
gameRole.restore(startMemento);
//显示
gameRole.descState();
}
代码层面讲
根据需要复制存储的对象,创建一个备忘录类,获取对象当前时刻的数据,赋值给备忘录,将备忘录对象存储到负责人容器中,在存储时根据需求选择合适的容器,例如当前,可以存储多个游戏角色多个时刻的状态,使用 Map,key为游戏角色id,value中的List中存储了该角色多个时刻的备忘录,假设只存储一个角色的多个时刻备忘录,使用List作为容器,下标为时刻,负责人提供存储与获取某个时刻备忘录的方法,原发器中提供获取当前数据的备忘录,与根据备忘录恢复数据的方法
为了节约内存,备忘录模式可以配合原型模式使用