备忘录模式

备忘录模式(Memento Pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。它是一种对象行为型模式,其别名为Token。
Originator(原发器):它是一个普通类,可以创建一个备忘录,并存储它的当前内部状态,也可以使用备忘录来恢复其内部状态,一般将需要保存内部状态的类设计为原发器。
Memento(备忘录):存储原发器的内部状态,根据原发器来决定保存哪些内部状态。备忘录的设计一般可以参考原发器的设计,根据实际需要确定备忘录类中的属性。需要注意的是,除了原发器本身与负责人类之外,备忘录对象不能直接供其他类使用,原发器的设计在不同的编程语言中实现机制会有所不同。
Caretaker(负责人):负责人又称为管理者,它负责保存备忘录,但是不能对备忘录的内容进行操作或检查。在负责人类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象,也无须知道对象的实现细节
示例1

以象棋中的悔棋为例说明。象棋走一步,将位置信息存储在memento中,可以悔一步棋

  • 象棋类(Originator原发器)
public class Chessman {
    private String label;
    private Integer x;
    private Integer y;

    public Chessman(String label, Integer x, Integer y) {
        this.label = label;
        this.x = x;
        this.y = y;
    }

    public ChessmanMemento getMemento() {
        return new ChessmanMemento(this.label,this.x,this.y);
    }

    public void restoreMemento(ChessmanMemento memento) {
        this.label = memento.getLabel();
        this.x = memento.getX();
        this.y = memento.getY();
    }

    @Override
    public String toString() {
        return "Chessman{" +
                "label='" + label + '\'' +
                ", x=" + x +
                ", y=" + y +
                '}';
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    public Integer getX() {
        return x;
    }

    public void setX(Integer x) {
        this.x = x;
    }

    public Integer getY() {
        return y;
    }

    public void setY(Integer y) {
        this.y = y;
    }
}
  • 备忘录(Memento)
public class ChessmanMemento {
    private String label;
    private Integer x;
    private Integer y;

    public ChessmanMemento(String label, Integer x, Integer y) {
        this.label = label;
        this.x = x;
        this.y = y;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    public Integer getX() {
        return x;
    }

    public void setX(Integer x) {
        this.x = x;
    }

    public Integer getY() {
        return y;
    }

    public void setY(Integer y) {
        this.y = y;
    }
}
  • 负责管理类(Caretaker)
public class MementoCaretaker {
    private ChessmanMemento memento;

    public ChessmanMemento getMemento() {
        return memento;
    }

    public void setMemento(ChessmanMemento memento) {
        this.memento = memento;
    }
}
  • 测试类
public class Memento01Test {
    public static void main(String[] args) {
        Chessman chessman = new Chessman("车", 5, 6);
        System.out.println("chessman = " + chessman);
        ChessmanMemento memento = chessman.getMemento();
        MementoCaretaker mementoCaretaker = new MementoCaretaker();
        mementoCaretaker.setMemento(memento);

        chessman.setX(6);
        chessman.setY(8);
        System.out.println("chessman = " + chessman);

        chessman.restoreMemento(mementoCaretaker.getMemento());
        System.out.println("chessman = " + chessman);

        /**
         * chessman = Chessman{label='车', x=5, y=6}
         * chessman = Chessman{label='车', x=6, y=8}
         * chessman = Chessman{label='车', x=5, y=6}
         */


    }
}

上述例子只能恢复一步,如果需要恢复多步,可以采用列表在管理类中管理状态。

总结
  • 优点

    • 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态
    • 实现了信息的封装,使得用户不需要关心状态的保存细节
  • 缺点

    • 如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存
  • 适用场景

    • 保存一个对象在某一个时刻的全部状态或部分状态,这样以后需要时它能够恢复到先前的状态,实现撤销操作
  • 应用

    • ctrl+z
    • 游戏存档
    • 浏览器后退
    • 数据库事务管理里

lijingyulee
91 声望7 粉丝

« 上一篇
中介者模式
下一篇 »
职责链模式