Java设计模式之备忘录模式

备忘录模式(Memento pattern): 当你需要让对象返回之前的状态时(例如, 你的用户请求”撤销”), 你使用备忘录模式。

备忘录模式的详解

类图:

Java设计模式之备忘录模式_第1张图片

角色说明:
发起人角色(Originator):此角色主要负责创建一个含有当前内部状态的备忘录对象,并使用被网罗对象存储其内部状态。

负责人角色(Caretaker):负责人角色主要负责保存备忘录对象,但不检查备忘录对象的内容。

备忘录角色(Memento):备忘录主要负责将发起人对象(Originator)的内部状态存储起来。备忘录可以根据发起人对象的判断来决定存储多少发起人对象的内部状态。备忘录还可以保护其内容不被发起人对象之外的任何对象所读取。

备忘录有两个等效的接口:

宽接口:发起人对象可以看到一个宽接口,这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。

窄接口:负责人对象(和其他除发起人对象之外的任何对象)看到的是备忘录的窄接口,这个窄接口只允许它把备忘录对象传给其他的对象。

透明备忘录模式

备忘录角色对任何对象都提供一个接口,即上面说的宽接口。备忘录角色的内容所存储的状态就对所有对象公开,所以又叫透明实现。

代码演示,发起人角色类:

/**
 * 发起人角色类
 * @author Layne
 *
 */
public class Originator {

    private String state;

    /**
     * 工厂方法,返回一个新的备忘录对象,并将发起人的状态传入
     */
    public Memento createMemento() {
        return new Memento(state);
    }

    /**
     * 将发起人恢复到备忘录对象所记载的状态
     */
    public void restoreMemento(Memento memento) {
        this.state = memento.getState();
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

}

负责人角色类:

/**
 * 负责人角色类
 * @author Layne
 *
 */
public class Caretaker {
    //持有一个备忘录对象
    private Memento memento;

    /**
     * 备忘录的取值方法
     */
    public Memento retrieveMemento() {
        return this.memento;
    }

    /**
     * 备忘录的赋值方法
     */
    public void saveMemento(Memento memento) {
        this.memento = memento;
    }
}

备忘录角色类:

/**
 * 备忘录角色类
 * @author Layne
 *
 */
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;
    }

}

客户端测试类:

public class Client {

    public static void main(String[] args) {

        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();

        // 设置负责人对象的状态
        originator.setState("smile");
        System.out.println("初始状态:"+originator.getState());


        // 创建备忘录对象,并将发起人对象的状态储存起来
        caretaker.saveMemento(originator.createMemento());
        // 修改发起人的状态
        originator.setState("cry");
        System.out.println("修改后状态:"+originator.getState());

        // 恢复发起人对象的状态
        originator.restoreMemento(caretaker.retrieveMemento());
        System.out.println("恢复后状态:"+originator.getState());
    }

}

运行结果:
Java设计模式之备忘录模式_第2张图片


隐藏备忘录模式

备忘录角色对发起人角色提供了一个宽接口,而对其他对象提供一个窄接口,所以又叫隐藏实现。

将备忘录类(Memento)设计成发起人类(Originator)的内部类。从而将备忘录类对象封装在发起人类里面;在外部提供一个标识接口MementoImpl给负责人类(Caretaker)以及其他对象。
这样发起人类看到的是备忘录类的所有接口,而负责人类记忆其他对象看到的仅仅是标识接口MementoImpl所暴露出来的接口。

类图:

Java设计模式之备忘录模式_第3张图片

代码演示,标识接口:

//标识接口
public interface MementoImpl {

}

负责人角色类:

public class Caretaker {

    private MementoImpl memento;

    /**
     * 备忘录取值方法
     */
    public MementoImpl retrieveMemento() {
        return memento;
    }

    /**
     * 备忘录赋值方法
     */
    public void saveMemento(MementoImpl memento) {
        this.memento = memento;
    }
}

发起人角色类:

public class Originator {

    private String state;

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    /**
     * 工厂方法,返还一个新的备忘录对象
     */
    public MementoImpl createMemento() {
        return new Memento(state);
    }

    /**
     * 发起人恢复到备忘录对象记录的状态
     */
    public void restoreMemento(MementoImpl memento) {
        this.setState(((Memento) memento).getState());
    }

    private class Memento implements MementoImpl {

        private String state;

        /**
         * 构造方法
         */
        private Memento(String state) {
            this.state = state;
        }

        private String getState() {
            return state;
        }
    }
}

客户端测试类:

public class Client {

    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();
        // 改变负责人对象的状态
        originator.setState("smile");
        System.out.println("初始状态:"+originator.getState());


        // 创建备忘录对象,并将发起人对象的状态存储起来
        caretaker.saveMemento(originator.createMemento());
        // 修改发起人对象的状态
        originator.setState("cry");
        System.out.println("修改后状态:"+originator.getState());

        // 恢复发起人对象的状态
        originator.restoreMemento(caretaker.retrieveMemento());
        System.out.println("恢复后状态:"+originator.getState());
    }

}

运行结果:
这里写图片描述

备忘录模式优点:

  • 当发起人角色中的状态改变时,有可能这是个错误的改变,我们使用备忘录模式就可以把这个错误的改变还原。
  • 备份的状态是保存在发起人角色之外的,这样发起人角色就不需要对各个备份的状态进行管理。

缺点:

  • 在实际应用中,备忘录模式都是多状态和多备份的,发起人角色的状态需要存储到备忘录对象中,对资源的消耗是比较严重的。

你可能感兴趣的:(Java设计模式)