定义
备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式。
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
备忘录模式常常与命令模式和迭代子模式一同使用。
结构
发起者角色(Originator):负责创建一个备忘录用以记录当前时刻它的内部状态,并可以使用备忘录恢复内部状态。
备忘录角色(Memento):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。
管理者角色(CareTake):负责保存好备忘录。
理解
备忘录只是为了存储 某对象的 某时刻的状态和信息 以及 恢复该状态
命令模式中提到 命令需要记录以及可以恢复,如果命令已经执行,那么就需要恢复数据和状态,就可以使用备忘录模式
备忘录需要一个对象状态信息的Entity类,对象自身需要有获取和恢复状态信息的方法,获取的对象信息和需要恢复的信息 需要存储,这就对应了上面的三个角色
根据 管理者角色 是否可以对获取的对象信息修改,分为白箱和黑箱模式,白箱就是可以操作,黑箱就是不可以操作。
白箱备忘录模式
类图
实现
/**
* 快照的对象
* 需要有生成快照和恢复快照两个方法
*/
public class Originator {
private String name;
private int state;
public Originator(String name, int state) {
this.name = name;
this.state = state;
}
/**
* 生成快照信息
*/
public Memento createMemento() {
return new Memento(name,state);
}
/**
* 还原快照信息
*/
public void recoveryMemento(Memento memento) {
this.name = memento.getName();
this.state = memento.getState();
}
//getter,setter,toString 方法
}
快照实体类
public class Memento {
private String name;
private int state;
//getter,setter,toString 方法
}
管理者
/**
* 管理者
*/
public interface CareTakeService {
/**
* 保存快照数据
* @param memento
*/
public void saveMemonto(Memento memento);
/**
* 恢复数据
* @param memento
* @return
*/
public Memento recoveryMemonto(Memento memento);
}
/**
* 管理者,用来保存快照 和 获取快照信息
*/
public class CareTaker implements CareTakeService{
/**
* 缓存数据
*/
private HashMap<Integer, Memento> snapshotMap = new HashMap<>();
/**
* 存储快照信息
* @param memento
*/
public void saveMemonto(Memento memento) {
snapshotMap.put(memento.getState(), memento);
}
/**
* 设定规则是设定状态的前一种的快照信息
* 这个规则不同的场景不同
* @param memento
* @return
*/
public Memento recoveryMemonto(Memento memento) {
return snapshotMap.get(memento.getState()-1);
}
}
调用类
public class Client {
public static void main(String[] args) {
Originator Originator = new Originator("11111",1);
System.out.println("当前状态:"+Originator.toString());
//获取快照信息
Memento memento = Originator.createMemento();
//保持快照信息
CareTaker taker = new CareTaker();
taker.saveMemonto(memento);
//修改状态
Originator.setName("nam322222");
Originator.setState(2);
System.out.println("修改后:"+Originator.toString());
//获取上一个记录的备忘录信息
Memento memento1 = taker.recoveryMemonto(Originator.createMemento());
//TODO 可以修改快照数据,原因是出来的是实体类当然能修改,如果换为接口就不能修改了
memento1.setState(memento1.getState());
//根据备忘录恢复数据
Originator.recoveryMemento(memento1);
System.out.println("恢复后:"+Originator.toString());
}
}
黑箱备忘录模式
类图
实现
/**
* 快照实体接口
* 只是用来做标记,标记传入这么一个类
* 如果你拿到很一个类,将没法做任何操作
*/
public interface MementoI {
}
public class Memento implements MementoI{
private String name;
private int state;
public Memento() {
}
public Memento(String name, int state) {
this.name = name;
this.state = state;
}
//getter & setter 方法
}
public class Originator{
private String name;
private int state;
public Originator(String name, int state) {
this.name = name;
this.state = state;
}
/**
* 生成快照信息
*/
public MementoI createMemento() {
return new Memento(name,state);
}
/**
* 还原快照信息
*/
public void recoveryMemento(MementoI memento1) {
Memento memento = (Memento)memento1;
this.name = memento.getName();
this.state = memento.getState();
}
//getter & setter & toString 方法
}
/**
* 管理者
*/
public interface CareTakeService {
/**
* 保存快照数据
* @param memento
*/
public void saveMemonto(MementoI memento);
/**
* 恢复数据
* @param memento
* @return
*/
public MementoI recoveryMemonto(MementoI memento);
}
/**
* 管理者,用来保存快照 和 获取快照信息
*/
public class CareTaker implements CareTakeService{
/**
* 缓存数据
*/
private HashMap<Integer, MementoI> snapshotMap = new HashMap<>();
/**
* 存储快照信息
* @param memento
*/
public void saveMemonto(MementoI memento) {
snapshotMap.put(((Memento)memento).getState(), memento);
}
/**
* 设定规则是设定状态的前一种的快照信息
* 这个规则不同的场景不同
* @param memento
* @return
*/
public MementoI recoveryMemonto(MementoI memento) {
return snapshotMap.get(((Memento)memento).getState()-1);
}
}
public class Client {
public static void main(String[] args) {
Originator Originator = new Originator("11111",1);
System.out.println("当前状态:"+Originator.toString());
//获取快照信息
MementoI memento = Originator.createMemento();
//保持快照信息
CareTaker taker = new CareTaker();
taker.saveMemonto(memento);
//修改状态
Originator.setName("nam322222");
Originator.setState(2);
System.out.println("修改后:"+Originator.toString());
//获取上一个记录的备忘录信息
MementoI memento1 = taker.recoveryMemonto(Originator.createMemento());
//TODO 可以修改快照数据,原因是出来的是实体类当然能修改,如果换为接口就不能修改了
//memento1.setState(memento1.getState());
//根据备忘录恢复数据
Originator.recoveryMemento(memento1);
System.out.println("恢复后:"+Originator.toString());
}
}
附录
暂无