其目的是,在不违反封装原则的前提下.采集和备份一个对象的内部状态以便这个对象可以在以后恢复到之前的某个状态.
public class Client { private static Originator originator = new Originator(); private static Caretaker c = new Caretaker(); public static void main(String[] args) { // 该发起人对象的状态 originator.setState("On"); // 创建备忘录对象,并将发起人对象的状态存储起来 c.saveMemento(originator.createMemento()); // 修改发起人对象的状态 originator.setState("Off"); // 恢复发起人对象的状态 originator.restoreMemento(c.retrieveMemento()); } }
// 发起人角色 class Originator { private String state; // 工厂方法,返还一个新的备忘录对象 public Memento createMemento() { return new Memento(state); } // 将发起人恢复到备忘录对象所记载的状态 public void restoreMemento(Memento memento) { this.state = memento.getState(); } // 状态的取值方法 public String getState() { return this.state; } // 状态的赋值方法 public void setState(String state) { this.state = state; System.out.println("Current state = " + this.state); } }
/* * 备忘录模式要求备忘录对象提供两个不同的接口:一个宽接口提供给发起人对象,另一个窄接口提供给所有其他的对象,包括负责人对象。 * 宽接口允许发起人读取到所有的数据;窄接口只允许它把备忘录对象传给其他的对象而看不到内部的数据。 */ // 备忘录角色 class Memento { private String state; public Memento(String state) { this.state = state; } public String getState() { return this.state; } public void setState(String state) { this.state = state; } }
/* * 负责人角色负责保存备忘录对象,但是从不修改(甚至不查看)备忘录对象的内容(一个更好的实现是负责人对象根本无法从备忘录 对象中读取个修改其内容) */ // 负责人角色 class Caretaker { private Memento memento; // 备忘录的取值方法 public Memento retrieveMemento() { return this.memento; } // 备忘录的赋值方法 public void saveMemento(Memento memento) { this.memento = memento; } }
首先将发起人对象的状态设置成“On”(或者任何有效状态),并且创建一个备忘录对象将这个状态存储起来;然后将发起人对象的状态改成“Off”(或者任何状态);最后又将发起人对象恢复到备忘录对象所存储起来的状态,即“On”状态(或者先前所存储的任何状态)
备忘录系统运行的时序是这样的:
(1)将发起人对象的状态设置成“On”。
(2)调用发起人角色的createMemento()方法,创建一个备忘录对象将这个状态存储起来。
(3)将备忘录对象存储到负责人对象中去。
备忘录系统恢复的时序是这样的:
(1)将发起人对象的状态设置成“Off”;
(2)将备忘录对象从负责人对象中取出;
(3)将发起人对象恢复到备忘录对象所存储起来的状态,“On”状态。
白箱实现的优缺点
白箱实现的一个明显的好处是比较简单,因此常常用做教学目的。白箱实现的一个明显的缺点是破坏对发起人状态的封装。
//客户端 public class Client { private static Originator originator = new Originator(); private static Caretaker c = new Caretaker(); public static void main(String[] args) { // 该发起人对象的状态 originator.setState("On"); // 创建备忘录对象,并将发起人对象的状态存储起来 c.saveMemento(originator.createMemento()); // 修改发起人对象的状态 originator.setState("Off"); // 恢复发起人对象的状态 originator.restoreMemento(c.retrieveMemento()); } }
// 发起人角色 class Originator { private String state; public Originator() { } // 工厂方法,返还一个新的备忘录对象 public MementoIF createMemento() { return new Memento(this.state); } // 将发起人恢复到备忘录对象记录的状态 public void restoreMemento(MementoIF memento) { Memento aMemento = (Memento) memento; this.setState(aMemento.getState()); } public String getState() { return this.state; } public void setState(String state) { this.state = state; System.out.println("state =" + state); } protected class Memento implements MementoIF { private String savedState; public Memento(String someState) { this.savedState = someState; } private void setState(String someState) { savedState = someState; } private String getState() { return savedState; } } }
interface MementoIF { }
// 备忘录角色 class Memento implements MementoIF { private String state; public Memento(String state) { this.state = state; } public String getState() { return this.state; } public void setState(String state) { this.state = state; } }
class Caretaker { private MementoIF memento; public MementoIF retrieveMemento() { return this.memento; } public void saveMemento(MementoIF memento) { this.memento = memento; } }
黑箱实现运行时的时序为;
(1)将发起人对象的状态设置成“On”。
(2)调用发起人角色的 createMemento()方法,创建一个备忘录对象将这个状态存储起来。
(3)将备忘录对象存储到负责人对象中去。由于负责人对象拿到的仅是 MementoIF类型,因此无法读出备忘录内部的状态。
恢复时的时序为:
(1)将发起人对象的状态设置成“Off”;
(2)将备忘录对象从负责人对象中取出。注意此时仅能得到 MementoIF接口,因此无法读出此对象的内部状态
(3)将发起人对象的状态恢复成备忘录对象所存储起来的状态,,由于发起人对象的内部类Memento实现了MementoIF接口
这个内部类是传入的备忘录对象的真实类型,因此发起人对象可以利用内部类Memento 的私有 接口读出此对象的内部状态。
//发起人角色 import java.util.Vector; import java.util.Enumeration; public class Originator{ private Vector states; private int index; public Originator(){ states = new Vector(); index = 0; } public Memento createMementor(){ return new Mementor(states,index); } public void restoreMementor(Mementor memento){ states = memento.getStates(); index = memento.getIndex(); } public void setState(String state){ this.states.addElement(state); index ++; } //辅助方法,打印出所有的状态 public void printStates(){ System.out.println("Total number of states: " + index); for(Enumeration e = states.elements();e.hasMoreElements();){ system.out.println(e.nextElement()); } } }
//备忘录角色 import java.util.Vector; public class Memento{ private Vector states; private int index; //<span style="font-size: 14px; font-family: Arial, Helvetica, sans-serif;">备忘录的构造子克隆了传入的states,然后将克隆存入到备忘录对象内部,这是一个重要的细节,因为不这样的话,将会</span><pre title="备忘录(Memento Pattern)模式 【行为模式第一篇】" style="font-size: 14px;"> //将会造成客户端和备忘录对象持有对同一个Vector对象的引用,也可以同时修改这个Vector对象,会造成系统崩溃。public Memento(Vector states,int index){this.states = (Vector)states.clone();this.index = index;}//状态取值方法Vector getStates(){return states;}//检查点取值方法int getIndex(){return this.index;}}
//负责人角色 import java.util.Vector; public class Caretaker{ private Originator o; private Vector mementos = new Vector(); private int current; public Caretaker(Originator o){ this.o = o; current = 0; } public int createMemento(){ Memento memento = o.createMemento(); mementos.addElement(memento); return current ++; } //将发起人恢复到某个检查点 public void restoreMemento(int index){ Memento memento = (Memento)mementos.elementAt(index); o.restoreMemento(memento); } //某个检查点删除 public void removeMemento(int index){ mementos.removeElementAt(index); } }
//客户端 public class Client{ private static Originator o = new Originator(); private static Caretaker c = new Caretaker(o); public static void main(String[] args){ //改变状态 o.setState("state 0"); //建立一个检查点 c.createMemento(); //改变状态 o.setState("state 1"); c.createMemento(); o.setState("state 2"); c.createMemento(); o.setState("state 3"); c.createMemento(); o.setState("state 4"); c.createMemento(); o.printStates(); //恢复到第二个检查点 System.out.println("Restoring to 2"); c.restoreMemento(2); o.printStates(); System.out.println("Restoring to 0"); c.restoreMemento(0); o.printStates(); System.out.println("Restoring to 3"); c.restoreMemento(3); o.printStates(); } }
//窄接口 public interface MementoIF{}
//发起人角色 public class Originator{ public String state; public Originator(){} public void changeState(String state){ this.state = state; System.out.println("State has been changed to : " + state); } public Memento createMemento(){ return new Memento(this); } public void restoreMemento(MementoIF memento){ Memento m = (Memento)memento; changeState(m.state); } class Memento implements MementoIF{ private String state; private String getState(){ return state; } private Memento(Originator o){ this.state = o.state; } } }
//客户端 public class Client{ private static Originator o; private static MementoIF memento; public static void main(String args[]){ o = new Originator(); o.changeState("State 1"); memento = o.createMemento(); o.changeState("State 2"); o.restoreMemento(memento); } }