一、背景
在日常生活工作中,我们常常需要一些反悔的操作,例如:下棋时悔棋,编写文档时的撤销,查看网页时的后退;这些频繁的操作不需要存在磁盘中,只要将内存中的状态恢复一下即可。这里我们可以使用备忘录模式实现这一点。
二、概述
1:定义
备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将对象恢复到原先保存的状态。
2:类图结构
- Originator(发起人):备忘录的创建者
- Memento(备忘录):负责存储Originator的内部状态
- Caretaker(管理者):负责保存好备忘录
3.适用场景
Memento模式适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。我们把保存的细节给封装在了Memento中了,哪一天需要更改保存的细节也不会影响客户端。
三:实例分析
举一个备份游戏人物进度的例子
游戏角色:
public class GameRole {
private int vit; //生命力
private int atk; //攻击力
private int def; //防御力
//...
//保存角色状态
public RoleStateMemento saveState(){
return (new RoleStateMemento(vit, atk, def));
}
//恢复角色状态
public void recoverState(RoleStateMemento memento){
this.vit = memento.getVit();
this.atk = memento.getAtk();
this.def = memento.getDef();
}
}
游戏状态存储箱:
public class RoleStateMemento {
private int vit; //生命力
private int atk; //攻击力
private int def; //防御力
//可自定义存储游戏角色的相应状态
public RoleStateMemento(int vit, int atk, int def) {
this.vit = vit;
this.atk = atk;
this.def = 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 class RoleStateCaretaker {
private RoleStateMemento memento;
public RoleStateMemento getMemento() {
return memento;
}
public void setMemento(RoleStateMemento memento) {
this.memento = memento;
}
}
管理者这个角色主要是和客户端进行交互,解除了Memento和客户端耦合(Memento是一个不确定因素,可能保存角色的各种状态集合)
下面是客户端代码:
//大战boss前
GameRole xiaoyao = new GameRole();
xiaoyao.getInitState(); //进行角色初始化,三项指标都为100
xiaoyao.stateDisplay();
//保存进度
RoleStateCaretaker stateCaretaker = new RoleStateCaretaker();
stateCaretaker.setMemento(xiaoyao.saveState());
//大战boss,操作失误
xiaoyao.fight(); //三项指标下降严重
xiaoyao.stateDisplay();
//恢复状态
xiaoyao.recoverState(stateCaretaker.getMemento());
xiaoyao.stateDisplay();
参考书籍:《大话设计模式》