定义
在不破坏对象封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态
角色
发起人(Iterator):记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据
备忘录(Concrete Iterator):负责存储发起人对象的内部状态,在需要的时候提供发起人需要的内部状态
管理角色(Container):对备忘录进行管理,保存和提供备忘录
优点
- 当发起人角色中的状态改变时,有可能这是个错误的改变,使用备忘录模式就可以把这个错误的改变还原
- 备份的状态是保存在发起人角色之外的,这样,发起人角色就不需要对各个备份的状态进行管理
缺点
- 在实际应用中,备忘录模式都是多状态和多备份的,发起人角色的状态需要存储到备忘录对象中,对资源的消耗是比较严重的
适用场景
- 需要回滚的操作,如jdbc事务,ctrl+z操作
- 版本管理器也可以使用备忘录模式
备忘录有两个等效的接口:
- 窄接口:除了发起人之外的对象看到的是备忘录的窄接口(narrow interface),这个窄接口只允许它把备忘录对象传给其他的对象
- 宽接口:与负责人对象看到的窄接口相反的是,发起人对象可以看到一个宽接口(wide interface),这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态
白盒备忘录
备忘录角色对任何对象都提供一个接口,即宽接口,备忘录角色的内部所存储的状态就对所有对象公开。因此这个实现又叫做白盒实现”
白盒实现将发起人角色的状态存储在一个大家都看得到的地方,因此是破坏封装性的。但是通过程序员自律,同样可以在一定程度上实现模式的大部分用意。因此白盒实现仍然是有意义的
类图
package com.vapy.behavior.Memento.white;
/**
*
* @author vapy 2016年8月27日
*
* 负责人
*
*/
public class Caretaker {
//备忘录属性
private Memento memento;
//保存备忘录对象
public void saveMemento(Memento memento){
this.memento = memento;
}
//取回备忘录对象
public Memento retrieveMemento(){
return memento;
}
}
package com.vapy.behavior.Memento.white;
/**
*
* @author vapy 2016年8月27日
*
* 备忘录
*
*/
public class Memento {
//保存的状态
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Memento(String state){
super();
this.state = state;
}
}
package com.vapy.behavior.Memento.white;
/**
*
* @author vapy 2016年8月27日
*
* 管理角色
*
*/
public class Originator {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
//创建备忘录对象
public Memento createMemento(){
return new Memento(this.state);
}
//恢复状态
public void setMemento(Memento memento){
this.state = memento.getState();
}
}
package com.vapy.behavior.Memento.white;
public class Client {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("初始状态");
System.out.println("当前状态:" + originator.getState());
System.out.println("保存备忘录");
caretaker.saveMemento(originator.createMemento());
System.out.println("设置新状态");
originator.setState("新状态");
System.out.println("当前状态:" + originator.getState());
System.out.println("恢复原状态");
originator.setMemento(caretaker.retrieveMemento());
System.out.println("当前状态:" + originator.getState());
}
}
黑盒备忘录
备忘录角色对发起人(Originator)角色对象提供一个宽接口,而为其他对象提供一个窄接口。这样的实现叫做黑盒实现
类图
package com.vapy.behavior.Memento.black;
/**
*
* @author vapy 2016年8月27日
*
*/
public class Caretaker {
private IMemento memento;
public void saveMemento(IMemento memento){
this.memento = memento;
}
public IMemento retrieveMemento(){
return memento;
}
}
package com.vapy.behavior.Memento.black;
/**
*
* @author vapy 2016年8月27日
*
*/
//声明式接口,无任何方法
public interface IMemento {
}
package com.vapy.behavior.Memento.black;
/**
*
* @author vapy 2016年8月27日
*
*/
public class Memento implements IMemento {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Memento(String state){
super();
this.state = state;
}
}
package com.vapy.behavior.Memento.black;
/**
*
* @author vapy 2016年8月27日
*
*/
public class Originator {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public IMemento createMemento(){
return new Memento(this.state);
}
public void setMemento(IMemento memento){
this.state = ((Memento)memento).getState();
}
}
package com.vapy.behavior.Memento.black;
/**
*
* @author vapy 2016年8月27日
*
*/
public class Client {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("初始状态");
System.out.println("当前状态:" + originator.getState());
System.out.println("保存备忘录");
caretaker.saveMemento(originator.createMemento());
System.out.println("设置新状态");
originator.setState("新状态");
System.out.println("当前状态:" + originator.getState());
System.out.println("恢复原状态");
originator.setMemento(caretaker.retrieveMemento());
System.out.println("当前状态:" + originator.getState());
}
}
本文代码可在github查看:点击此处