> 文档中心 > 设计模式.备忘录模式 快照模式(Snapshot Pattern)或Token模式

设计模式.备忘录模式 快照模式(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());    }}

 附录

暂无