定义:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能够将该对象恢复到原先保存的状态。
适用场景:
1、数据库事务回滚
2、ctrl+z
3、ie浏览器回退操作
优点:
1、提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
2、实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息
3、简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则
缺点:
1、资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存空间。
组成元素:
1、发起人(Originator):记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,以及实现其他业务功能,它可以访问备忘录里的所有信息。
2、备忘录(Memento):负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
3、管理者(CareTaker):对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问和修改。
类图如下:
抽象代码如下:
1、定义备忘录Memento:
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
2、定义管理者Caretaker
public class Caretaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
3、定义发起人Originator
public class Originator {
private String state;
public Memento createMemento() {
return new Memento(state);
}
public void restoreMemento(Memento m) {
this.setState(m.getState());
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
4、定义客户类MementoPattern
public class MementoPattern {
public static void main(String[] args) {
Originator or = new Originator();
Caretaker cr = new Caretaker();
or.setState("S0");
System.out.println("初始状态:"+or.getState());
cr.setMemento(or.createMemento());
or.setState("S1");
System.out.println("新的状态:"+or.getState());
or.restoreMemento(cr.getMemento());
System.out.println("原始状态:"+or.getState());
}
}
5、输出结果如下:
示例代码如下:
由于于谦做了一件好事(扶老太太过马路),上帝决定给你奖励,上帝给了你四个箱子A、B、C、D,但是你只能选择一个,但是上帝是比较人性化的,它允许你反悔,即你先选择A,然后你反悔了选择B,这样也是可以的,我们用备忘录模式来实现一下这个例子。
1、定义箱子备忘录BoxMemento:
public class BoxMemento {
private String boxName;
public BoxMemento(String boxName) {
this.boxName = boxName;
}
public String getBoxName() {
return boxName;
}
public void setBoxName(String boxName) {
this.boxName = boxName;
}
}
2、定义箱子管理者BoxCaretaker,只保存最新的4种回退状态:
public class BoxCaretaker {
public List<BoxMemento> boxMementoList = new ArrayList<>();
private int top=0;
public boolean push(BoxMemento b){
if(top>=4){
boxMementoList.add(b);
boxMementoList.remove(0);
top--;
return true;
}else{
boxMementoList.add(b);
top++;
return true;
}
}
public BoxMemento pop(){
if(top<=0){
return boxMementoList.get(0);
}else {
return boxMementoList.get(--top);
}
}
}
3、定义发起人于谦OriginatorYuQian:
public class OriginatorYuQian {
private String boxName;
public BoxMemento createMemento() {
return new BoxMemento(boxName);
}
public void restoreMemento(BoxMemento m) {
this.setBoxName(m.getBoxName());
}
public String getBoxName() {
return boxName;
}
public void setBoxName(String boxName) {
this.boxName = boxName;
}
}
4、定义客户类MementoPattern:
public class MementoPattern {
public static void main(String[] args) {
OriginatorYuQian or = new OriginatorYuQian();
BoxCaretaker cr = new BoxCaretaker();
or.setBoxName("箱子A");
cr.push(or.createMemento());
or.setBoxName("箱子B");
cr.push(or.createMemento());
or.setBoxName("箱子C");
cr.push(or.createMemento());
or.setBoxName("箱子D");
cr.push(or.createMemento());
/*因为咱们只保存4种回退状态,若set第5次,则第一次set的状态清除掉。*/
// or.setBoxName("箱子E");
// cr.push(or.createMemento());
System.out.println("当前选择的箱子为:"+cr.boxMementoList.get(cr.boxMementoList.size()-1).getBoxName());
System.out.println("回退第一次选择的箱子为:"+cr.pop().getBoxName());
System.out.println("回退第二次选择的箱子为:"+cr.pop().getBoxName());
System.out.println("回退第三次选择的箱子为:"+cr.pop().getBoxName());
System.out.println("回退第四次选择的箱子为:"+cr.pop().getBoxName());
System.out.println("回退第五次选择的箱子为:"+cr.pop().getBoxName());
}
}
5、输出结果如下: