版本3源代码如下:
package备忘录模式;
//标识接口(窄接口)
publicinterfaceMementoIF {
}
package备忘录模式;
importjava.util.Vector;
publicclassOriginator {
privateVectorstates;
privateintindex;
publicOriginator(){
states=newVector();
index=0;
}
//工厂方法,返回一个新的备忘录对象
publicMementoIF createMemento(){
returnnewMemento(this.states,index);
}
//将发起人恢复到备忘录对象所记载的状态
publicvoidrestoreMemento(MementoIF memento){
states=((Memento)memento).getStates();
index=((Memento)memento).getIndex();
}
//状态的赋值方法
publicvoidsetState(Object state){
this.states.addElement(state);
index++;
}
//辅助方法,打印出所有状态
publicvoidprintStates(){
System.out.println("Total number of states:"+index);
for(Object o :states){
System.out.println(o.toString());
}
}
//内部类
protectedclassMementoimplementsMementoIF{
privateVectorsaveStates;
privateintsaveIndex;
@SuppressWarnings("unchecked")
//_states一定是Vector
privateMemento(Vector _states,int_index){
//保存客户端传来的状态对象的拷贝,否则客户端的修改会影响到保存的状态。
saveStates=(Vector)_states.clone();
saveIndex=_index;
}
privateVector getStates(){
returnsaveStates;
}
privateintgetIndex(){
returnsaveIndex;
}
}
}
package备忘录模式;
importjava.util.Vector;
publicclassCaretaker {
privateOriginatoro;
privateVectormementos=newVector();
privateintcurrentIndex;
publicCaretaker(Originator o){
this.o=o;
currentIndex=0;
}
//创建一个新的检查点
publicvoidcreateMemento(){
mementos.addElement(o.createMemento());
currentIndex++;
}
//将发起人恢复到某个检查点
publicvoidreStoreMemento(intindex){
o.restoreMemento(mementos.elementAt(index));
}
//删除某个检查点
publicvoidremoveMemento(intindex){
mementos.removeElementAt(index);
}
}
package备忘录模式;
publicclassClient {
publicstaticvoidmain(String[] args){
Originator o=newOriginator();
Caretaker c=newCaretaker(o);
//改变发起人的状态
o.setState("state0");
//创建一个检查点
c.createMemento();
o.setState("state1");
c.createMemento();
o.setState("state2");
c.createMemento();
o.setState("state3");
c.createMemento();
o.setState("state4");
c.createMemento();
//打印出所有状态
o.printStates();
//恢复到第3个检查点
System.out.println("Restoring to 3");
c.reStoreMemento(3);
o.printStates();
//恢复到第0个检查点
System.out.println("Restoring to 0");
c.reStoreMemento(0);
o.printStates();
//恢复到第4个检查点
System.out.println("Restoring to 4");
c.reStoreMemento(4);
o.printStates();
}
}
输出:
Total number of states:5
state0
state1
state2
state3
state4
Restoring to 3
Total number of states:4
state0
state1
state2
state3
Restoring to 0
Total number of states:1
state0
Restoring to 4
Total number of states:5
state0
state1
state2
state3
state4
跟版本1相比,负责人角色除了负责保存状态之外,还负责发起人状态的恢复,功能增强了。
注意
1.以上的内容基本上都可以从阎宏的《Java与模式》找到,我只是“取其精华并整理之”。完成以上的工作后,我发现有些东西需要补充一下,以免有误导。
2.“黑箱”备忘录的实现中,将Memento类做成Originator的内部类,并将其方法全部设置成private,其实这样一般来说就已经足够了,不需要再使用窄接口MementoIF。因为这样做的话外部拿到Memento类的实例,由于其方法都是private的,所以该方法只有Originator类可以调用,其它类是调用不了的,也就无法修改其中的内容。
3.那么窄接口什么时候使用呢,我觉得应该是这样,如果Memento类因为某些原因不能做成内部类,那么就应该定义两个接口,一个WideMemento,一个NarrowMemento(一般没有定义任何方法),前者供Originator类使用,后者供其它类使用。这样的缺点就是,外部只要将得到的实例强制转化为WideMemento类型,同样可以访问到Memento类的内容。
4.如果要继承Originator类并且不改变Memento类的代码,那么Memento类的方法应该设置成默认属性(package access),而不是private。
相关模式
命令模式:命令模式中使用备忘录模式来存储可撤销的操作的状态。