什么是备忘录模式
备忘录模式其实类似于我们常见的游戏存档和回档,会有一个对象专门存储某个对象某个时刻的状态(即属性值),这个对象就相当于一份备忘录,在需要的时候,我们可以将对象恢复到备忘录中记录的状态
备忘录模式有三个角色
originator
需要备份的对象
memento
保存备份的对象
caretaker
负责管理memento,这个对象只起到保存备份的作用,不能更改和查看备份,即memento对于caretaker来说是不可见的
接下来用java实现备忘录模式,备忘录模式有四种经典的实现方式,这里只介绍白箱和黑箱,尤其是黑箱,设计非常巧妙
白箱实现
白箱实现会有三个类,分别为originator、memento、caretaker
originator需要实现两个方法,一个方法返回mementor(备份)对象,一个方法根据mementor对象进行回档
originator
package memento;
/**
*
* @author lzy
*/
public class originator {
private String name;
private int age;
private String sex;
public originator(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
//创造备份对象memento
public memento createMemento(){
return new memento(name,age,sex);
}
//回档
public void setMemento(memento mem){
this.age=mem.getAge();
this.name=mem.getName();
this.sex=mem.getSex();
}
public void display(){
System.out.println("Age="+age+",Name="+name+",Sex="+sex);
}
}
memento:
memento和originator的属性相同,但是没有创造备份对象和回档的方法
package memento;
/**
*
* @author lzy
*/
public class memento {
private String name;
private int age;
private String sex;
public memento(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
caretaker:
creataker仅仅是保存对象,但在白箱实现中,通过caretaker可以知道和更改memento的值,虽然我们可以在memento不提供set方法,但是get方法是必须的(回档时需要使用),我们甚至可以自己实现一个memento,memento的封装性遭到破坏
package memento;
/**
*
* @author lzy
*/
public class caretaker {
private memento mem;
public memento getMem() {
return mem;
}
public void setMem(memento mem) {
this.mem = mem;
}
}
在main方法中进行测试
package memento;
/**
*
* @author lzy
*/
public class main {
public static void main(String[] args) {
originator per=new originator("菜到怀疑人生",18,"基佬");
caretaker tk=new caretaker();
tk.setMem(per.createMemento());
System.out.print("修改前:");
per.display();
per.setAge(100);
System.out.print("修改后:");
per.display();
per.setMemento(tk.getMem());
System.out.print("备份恢复后:");
per.display();
}
}
运行结果:
白箱实现虽然简单,但是memento的封装性遭到严重破坏
黑箱实现
在黑箱实现中,将memento作为originator的私有内部类,caretaker只有mementor的一个标识,这个标识为一个空接口(即没有任何方法和属性),memento会继承这个接口,空接口使caretaker无法查看mementor的值,将mementor置为私有内部类,这点最巧妙,我们无法通过originator对象来查看和更改memento的值,我们只能够通过originator提供的创造备份的方法来创造备份,不允许我们自己创建备份对象,黑箱实现克服了一系列白箱实现的缺点
mementoF:接口标识
package memorandum2;
/**
*
* @author lzy
*/
public interface mementoF {
}
originator与memento:
package memorandum2;
/**
*
* @author lzy
*/
public class originator {
private int state;
public originator(int state) {
this.state = state;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
private class memento implements mementoF{
private int state;
public memento(int state) {
this.state = state;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
}
public mementoF createMemento(){
return (mementoF)new memento(state);
}
public void retrieveMemento(mementoF mem){
this.state=((memento)mem).getState();
}
public void display(){
System.out.println("state="+state);
}
}
caretaker:
package memorandum2;
/**
*
* @author lzy
*/
public class caretaker {
private mementoF mem;
public mementoF getMemento() {
return mem;
}
public void setMemento(mementoF mem) {
this.mem = mem;
}
}
主函数就不写了,效果和白箱实现是一样的,但是封装性却进一步提高