设计模式——备忘录模式

一、什么是备忘录模式?

 

  备忘录(Memento)模式又叫做标记(Token)模式。备忘录中存放着对象的历史状态,当对象状态改变后,想要恢复先前的状态时,就可以使用备忘录来恢复


  备忘录模式中存在以下角色:


  1. 发起者(Originator)角色:创建一个备忘录,内部记录其此时的状态,需要时可以使用备忘录来恢复状态


  2. 备忘录(Memento)角色:储存着发起者内部的状态


  3. 备忘负责人(Caretaker)角色:用来对备忘进行存储,但在设计时不应该让备忘负责人有查看或操作备忘录对象的权限


  按照实现方式分类,备忘录模式可以分为两种:白箱模式和黑箱模式


  白箱模式,顾名思义,这种备忘录模式是“透明”的,即备忘录对象除了可以被发起人对象访问,还能被备忘负责人对象访问。这种模式简单方便,然后缺点也显而易见——封装没有设计好,缺少安全性


  黑箱模式就是白箱模式的一种改进,在黑箱模式中,备忘录对象只能被发起人对象访问——这也是比较合理的备忘录模式的设计思想。那么如何来实现黑箱模式呢?我们可以考虑内部类——备忘录类设计成发起者的内部类。然而这也有一个问题,那就是同一个package的其他类还可以访问备忘录类,为了解决这个问题,我们可以考虑把备忘录类方法设计成私有的,那么只有其本身及发起者类能访问!

 

二、备忘录模式框图




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

  白箱模式



设计模式——备忘录模式_第2张图片

  黑箱模式

 


三、备忘录模式的具体实现代码

 

1. 白箱模式


3.1 Originator——备忘录发起者

package designpatterns.memento.whiteBox;

/**
 * Created by Olive on 2017/12/22.
 * 发起者角色
 */
public class Originator {

    private String state;

    // 创建备忘录
    public Memento createMemento(){
        return new Memento(state);
    }

    // 恢复备忘对象的状态
    public void restoreMemento(Memento memento){
        this.state = memento.getState();
        System.out.println("Restore State == " + this.state);
    }

    public void setState(String state) {
        this.state = state;
        System.out.println("State == " + this.state);
    }

    public String getState() {
        return state;
    }

}

3.2 Memento——备忘录类

package designpatterns.memento.whiteBox;

/**
 * Created by Olive on 2017/12/22.
 */
public class Memento {

    private String state;

    public String getState() {
        return state;
    }

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

    public Memento(String state){
        this.state = state;
    }

}

3.3 Caretaker——备忘录负责人

package designpatterns.memento.whiteBox;

/**
 * Created by Olive on 2017/12/22.
 * 负责人角色,负责保存备忘录角色
 */
public class Caretaker {

    private Memento memento;

    public Memento getMemento() {
        return memento;
    }

    public void setMemento(Memento memento) {
        this.memento = memento;
    }

}

3.4 Client——客户端

package designpatterns.memento.whiteBox;

/**
 * Created by Olive on 2017/12/22.
 */
public class Client {

    public static void main(String[] args){
        // 创建备忘录发起者
        Originator originator = new Originator();
        // 创建备忘录负责人
        Caretaker caretaker = new Caretaker();

        // 设置需要备忘的状态,并创建备忘录至负责人处
        originator.setState("man");
        caretaker.setMemento(originator.createMemento());

        // 修改备忘对象的状态,然后恢复至之前的状态
        originator.setState("woman");
        originator.restoreMemento(caretaker.getMemento());

    }
}

3.5 结果

State == man
State == woman
Restore State == man

Process finished with exit code 0

 

白箱模式的备忘录模式,caretaker对象很容易根据getMemento方法获取Memento对象内部存储的状态,这样安全性就不足了。以下使用黑箱模式解决这个问题:

 

2. 黑箱模式


3.6 NarrowMemento——抽象备忘录接口

package designpatterns.memento.blackBox;

/**
 * Created by Olive on 2017/12/22.
 */
public interface NarrowMemento {
    void narrowMethod();
}

3.7 Originator——备忘录发起者

package designpatterns.memento.blackBox;

/**
 * Created by Olive on 2017/12/22.
 * 发起者角色
 */
public class Originator {

    private String state;
    // 内部还包含一个备忘录对象的引用
    private NarrowMemento memento;

    // 创建备忘录
    public NarrowMemento createMemento(){
        memento = new Memento(state);
        return memento;
    }

    // 恢复备忘对象的状态
    public void restoreMemento(NarrowMemento memento){
        // 类型转换
        Memento aMemento = (Memento) memento;
        this.state = aMemento.getState();
        System.out.println("Restore State == " + this.state);
    }

    public void setState(String state) {
        this.state = state;
        System.out.println("State == " + this.state);
    }

    public String getState() {
        return state;
    }

    // 返回Originator类中的memento对象
    public NarrowMemento getNarrowMemento(){
        return memento;
    }

    // 此时的Memento为Originator类的内部类
    protected class Memento implements NarrowMemento{

        private String state;

        // 私有的构造方法,所以只有Memento及Originator类能访问
        private Memento(String state){
            this.state = state;
        }


        public void narrowMethod() {
            System.out.println("Using narrow method");
        }

        private String getState() {
            return state;
        }

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

    }

}

3.8 Caretaker——备忘录负责人

package designpatterns.memento.blackBox;

/**
 * Created by Olive on 2017/12/22.
 * 负责人角色,负责保存备忘录角色
 */
public class Caretaker {

    private NarrowMemento memento;

    public NarrowMemento getMemento() {
        return memento;
    }

    public void setMemento(NarrowMemento memento) {
        this.memento = memento;
    }

}

3.9 Client——客户端

package designpatterns.memento.blackBox;

/**
 * Created by Olive on 2017/12/22.
 */
public class Client {

    public static void main(String[] args){
        // 创建备忘录发起者
        Originator originator = new Originator();
        // 创建备忘录负责人
        Caretaker caretaker = new Caretaker();

        // 设置需要备忘的状态,并创建备忘录至负责人处
        originator.setState("man");
        caretaker.setMemento(originator.createMemento());

        // 修改备忘对象的状态,然后恢复至之前的状态
        originator.setState("woman");
        originator.restoreMemento(caretaker.getMemento());

        NarrowMemento memento = originator.getNarrowMemento();
        memento.narrowMethod();

    }
}

3.10 结果

State == man
State == woman
Restore State == man
Using narrow method

Process finished with exit code 0

 

你可能感兴趣的:(Java)