Java DesignPartten Code

设计模式-备忘录模式

Posted on 2020-10-28,4 min read

定义

  • Without violating encapsulation,capture and externalize an object's internal state so that the object can be restored to this state later.(在不破坏封装性的前提下,捕获一个对象的内部状 态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。)

  • 角色

    • Originator发起人角色:记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录 数据。
    • Memento备忘录角色:负责存储Originator发起人对象的内部状态,在需要的时候提供发起人需要的内部状态。
    • Caretaker备忘录管理员角色:对备忘录进行管理、保存和提供备忘录
  • 通用类图:

    备忘录模式通用类图

优点

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

缺点

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

使用场景

  • 场景:
    • 需要保存和恢复数据的相关状态场景。
    • 提供一个可回滚(rollback)的操作;比如Word中的CTRL+Z组合键,IE浏览器中的后退按钮,文件管理器上的backspace键等。
    • 需要监控的副本场景中。例如要监控一个对象的属性,但是监控又不应该作为系统的主业务来调用,它只是边缘应用,即使出现监控不准、错误报警也影响不大,因此一般的做法是备份一个主线程中的对象,然后由分析程序来分析
    • 数据库连接的事务管理就是用的备忘录模式

代码

备忘录模式

代码

package com.pattern.memento.template;

public class MementoPattern {
    public static void main(String[] args) {
        //定义出发起人
        Originator originator = new Originator();
        //定义出备忘录管理员
        Caretaker caretaker = new Caretaker();
        //创建一个备忘录
        caretaker.setMemento(originator.createMemento());
        //恢复一个备忘录
        originator.restoreMemento(caretaker.getMemento());
    }
}

/**
 * 发起人角色
 */
class Originator {
    //内部状态
    private String state = "";
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }

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

    //恢复一个备忘录
    public void restoreMemento(Memento _memento) {
        this.setState(_memento.getState());
    }
}

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

/**
 * 备忘录管理员角色
 */
class Caretaker {
    //备忘录对象
    private Memento memento;

    public Memento getMemento() {
        return memento;
    }

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

注意

  • 由于备忘录模式有太多的变形和处理方式,每种方式都有它自己的优点和缺点,标准的备忘录模式很难在项目中遇到,基本上都有一些变换处理方式。因此,在使用备忘录模式时主要了解如何应用以及需要注意哪些事项就成了。
  • 备忘录的生命期:备忘录创建出来就要在“最近”的代码中使用,要主动管理它的生命周期,建立就要使用,不使用就要立刻删除其引用,等待垃圾回收器对它的回收处理。
  • 不要在频繁建立备份的场景中使用备忘录模式(比如一个for循环中),原因有二:一是控制不了备忘录建立的对象数量;二是大对象的建立是要消耗资源的
  • 使用Clone方式的备忘录模式,可以使用在比较简单的场景或者比较单一的场景中,尽量不要与其他的对象产生严重的耦合关系
  • 如果要设计一个在运行期决定备份状态的框架,建议使用AOP框架来实现
  • 要严格限制备忘录的创建,增加备份容器的容量上限,否则系统很容易内存溢出

下一篇: 设计模式-解释器模式→

loading...