1 定义
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
2 适用场景
- Memento模式适用于功能比较复杂的,需要维护或记录属性历史的类 or 需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。
- 有时一些对象的内部信息必须保存在对象外的地方,但是必须由对象自己读取,这时,使用备忘录可以把复杂的对象内部信息对其他的对象屏蔽。
- 最大的作用是:当角色的状态改变的时候,这个状态有可能无效,这时使用备忘录将状态复原。
3 缺点
如果状态数据很多很大,备忘录对象对非常消耗内存。
4 UML图
5 例子
5.1 场景
某个游戏角色a有3个属性:生命力、攻击力、防御力。在角色a攻击角色b之前,这三个属性是一个状态值;攻击完b后,这三个属性值是另一个状态值;此时借助角色存储备忘录Memento,恢复a攻击前的状态值。
5.2 UML图
5.3 代码
Main
public class Main {
public static void main(String[] args) {
GameRole gameRole=new GameRole();
//初始状态
gameRole.getInitState();
gameRole.stateDisplay();
//保存状态
RoleStateCaretaker caretaker=new RoleStateCaretaker();
caretaker.setMemento(gameRole.saveState());
//作战
gameRole.fight();
gameRole.stateDisplay();
//恢复状态
gameRole.recoveryState(caretaker.getMemento());
gameRole.stateDisplay();
}
}
GameRole
public class GameRole {
private int vit;//生命力
private int atk;//攻击力
private int def;//防御力
//初始化状态
public void getInitState(){
this.vit=100;
this.atk=100;
this.def=100;
}
//状态显示
public void stateDisplay(){
System.out.println(String.format("生命力:%d",this.vit));
System.out.println(String.format("攻击力:%d",this.atk));
System.out.println(String.format("防御力:%d",this.def));
}
//战斗
public void fight(){
this.vit=21;
this.atk=12;
this.def=33;
}
//保存角色状态
public RoleStateMemento saveState(){
return new RoleStateMemento(vit,atk,def);
}
//恢复角色状态
public void recoveryState(RoleStateMemento memento ){
this.vit=memento.getVit();
this.atk=memento.getAtk();
this.def=memento.getDef();
}
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;
}
}
RoleStateMemento
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;
}
}
RoleStateCaretaker
public class RoleStateCaretaker {
private RoleStateMemento memento;
public RoleStateMemento getMemento() {
return memento;
}
public void setMemento(RoleStateMemento memento) {
this.memento = memento;
}
}