0x00 概述
备忘录模式提供了一种类似于版本控制的功能,使得用户可以回退到特定的一个版本,常见的undo、redo就是典型的代表。
在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。它是一种对象行为型模式,其别名为Token。
0x01 组成部分
- Originator:原发器,通常将需要保存内部状态的类设计为原发器,一般设有createMemento()和restoreFromMemento(Memento m)两个方法,前者用于创建一个版本的备忘录对象,后者用于从备忘录中恢复状态。
- Memento:备忘录,用于存储原发器的内部状态,只允许原发器和负责人访问,不允许其他对象访问。
- MementoCareTaker,负责人,仅仅用于存储备忘录对象,不允许操作改变备忘录对象状态。
UML架构图如下:
0x10 示例代码
以下代码以undo、redo功能为例。
package com.kkk.pattern.memento;
/**
* 数学计算公式,充当原发器。
* Created by z3jjlzt on 2018/2/5.
*/
public class Formula {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
/**
* 创建一个备忘录。
* @return
*/
public Memento createMemento() {
Memento memento = new Memento();
memento.setMstate(getState());
return memento;
}
public void restoreFromMemento(Memento memento) {
this.state = memento.getMstate();
}
public Memento op(String state) {
Memento memento = createMemento();
this.state = this.state + state;
return memento;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Formula{");
sb.append("state='").append(state).append('\'');
sb.append('}');
return sb.toString();
}
/**
* 备忘录类。
* Created by z3jjlzt on 2018/2/5.
*/
class Memento {
private String mstate;
public String getMstate() {
return mstate;
}
public void setMstate(String mstate) {
this.mstate = mstate;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Memento{");
sb.append("mstate='").append(mstate).append('\'');
sb.append('}');
return sb.toString();
}
}
/**
* 负责类.作用仅仅是存储备忘录对象,而不允许改变备忘录对象。
* Created by z3jjlzt on 2018/2/5.
*/
public class MementoCaretaker {
private Stack<Memento> undolst = new Stack<>();
private Stack<Memento> redolst = new Stack<>();
/**
* 进行新的操作.
*/
public void operator(Memento memento) {
redolst.clear();//先清空redo栈.
undolst.push(memento);
}
public Memento undo(Formula formula) {
redolst.push(formula.createMemento());
return undolst.pop();
}
public Memento redo(Formula formula) {
undolst.push(formula.createMemento());
return redolst.pop();
}
}
/**
* Created by z3jjlzt on 2018/2/5.
*/
public class Client {
public static void main(String[] args) {
Formula formula = new Formula();
formula.setState("1*3");
MementoCaretaker caretaker = new MementoCaretaker();
Memento op = formula.op("-4");
caretaker.operator(op);
Memento op1 = formula.op("*5");
caretaker.operator(op1);
Memento op2 = formula.op("/6");
caretaker.operator(op2);
System.out.println(formula);
formula.restoreFromMemento(caretaker.undo(formula));
System.out.println(formula);
formula.restoreFromMemento(caretaker.redo(formula));
System.out.println(formula);
formula.restoreFromMemento(caretaker.undo(formula));
System.out.println(formula);
formula.restoreFromMemento(caretaker.undo(formula));
System.out.println(formula);
formula.restoreFromMemento(caretaker.undo(formula));
System.out.println(formula);
formula.restoreFromMemento(caretaker.redo(formula));
System.out.println(formula);
formula.restoreFromMemento(caretaker.redo(formula));
System.out.println(formula);
formula.restoreFromMemento(caretaker.redo(formula));
System.out.println(formula);
}
}
运行结果:
Formula{state='1*3-4*5/6'}
Formula{state='1*3-4*5'}
Formula{state='1*3-4*5/6'}
Formula{state='1*3-4*5'}
Formula{state='1*3-4'}
Formula{state='1*3'}
Formula{state='1*3-4'}
Formula{state='1*3-4*5'}
Formula{state='1*3-4*5/6'}
0xff 总结
- 优点:提供了一种状态恢复的机制。
- 缺点:在原发器的state数目过多时,资源消耗过大。
- 适用场景:系统需要提供状态恢复的机制。