设计模式.备忘录模式 快照模式(Snapshot Pattern)或Token模式
定义
备忘录模式又叫做快照模式(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 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 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()); }}
附录
暂无