设计模式-备忘录模式 本质:保存和恢复对象状态(部分状态) 不破坏封装性的前提下,获取一个对象的内部状态,并在该对象外保存这个状态。 Memento模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者保护的属性只是众多属性中的一小部分。 典型例子: 游戏大战Boss前会保存记录。
UML图:
下面用一个30岁的中年人想穿越回10岁小孩的例子来模拟下这个备忘录模式。
先来个Person类:
Person有基本的年龄和力量属性,这个 穿越时,会变化,但是记忆是不会变化的,如果记忆也变化了,那么就不是穿越了,哈哈。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Person {
private int age;//年龄
private int power;//力量
private List<String> rememberList = new ArrayList<>();//记忆 这个属性是不用写进备忘录的,即使穿越了也会有的
public void show(){
System.out.println("age:"+age+" power:"+power+" remember:"+ Arrays.toString(rememberList.toArray()));
System.out.println();
}
/**
* 记录此时此刻
*/
public PersonMemento record(){
PersonMemento personMemento = new PersonMemento();
personMemento.setAge(this.getAge());
personMemento.setPower(this.getPower());
return personMemento;
}
/**
* 重新来一次
* @param personMemento
*/
public void reback(PersonMemento personMemento){
this.age = personMemento.getAge();
this.power = personMemento.getPower();
}
//getter and setter
}
备忘录类:
这个类的属性是Person的部分属性,用来保存当时的状态。
问:可以直接用Person类吗?
答:如果大部门属性都一样,是可以的,这时可以用原型模式进行复制。但是如果类属性特别多,但是需要备忘的数据特别少,那么就建议使用备忘录类。
/**
* 人物备忘录
*/
public class PersonMemento {
private int age;
private int power;
//getter and setter
}
备忘录管理者类:
备忘录 管理者,主要就是 对 备忘录的 存和拿。
/**
* 时间之神 备忘录管理者
*/
public class TimeGod {
private PersonMemento personMemento;
//getter and setter
public PersonMemento getPersonMemento() {
return personMemento;
}
public void setPersonMemento(PersonMemento personMemento) {
this.personMemento = personMemento;
}
}
调用者(测试类):
public class Test {
public static void main(String[] args) {
TimeGod timeGod = new TimeGod();//时间之神,备忘录管理者
System.out.println("10岁 主人公出场了");
Person person = new Person();
//年龄10岁 能力15
person.setAge(10);
person.setPower(15);
person.getRememberList().add("那年我10岁,但是能力只有15,不能自己买棒棒糖给自己。\n");
System.out.print("现在状态:" );
person.show();
//
System.out.println("时间之神默默记录下了当时的情况");
timeGod.setPersonMemento(person.record());
System.out.println("主人公长大了");
person.setAge(30);
person.setPower(200);
person.getRememberList().add("现在我已经30岁了,有很大的能力是,可以买很多棒棒糖了。\n");
System.out.print("现在状态:" );
person.show();
System.out.println("他向时间之神许了个愿望,想回到10岁,时间之神答应了");
person.reback(timeGod.getPersonMemento());
System.out.println("回到过去...");
System.out.print("现在状态:" );
person.show();
}
}
测试输出结果:
10岁 主人公出场了
现在状态:age:10 power:15 remember:[那年我10岁,但是能力只有15,不能自己买棒棒糖给自己。
]
时间之神默默记录下了当时的情况
主人公长大了
现在状态:age:30 power:200 remember:[那年我10岁,但是能力只有15,不能自己买棒棒糖给自己。
, 现在我已经30岁了,有很大的能力是,可以买很多棒棒糖了。
]
他向时间之神许了个愿望,想回到10岁,时间之神答应了
回到过去...
现在状态:age:10 power:15 remember:[那年我10岁,但是能力只有15,不能自己买棒棒糖给自己。
, 现在我已经30岁了,有很大的能力是,可以买很多棒棒糖了。
]
优化:
上面的例子备忘录只有一个,可以做成多个,在关键节点都进行状态保存。
上诉说到原型模式,如果你还对此模式不是很了解,可以查阅笔者的博客: