美文网首页
设计模式之十九——备忘录模式

设计模式之十九——备忘录模式

作者: dd299 | 来源:发表于2019-07-01 23:36 被阅读0次

    原文传送门

    1 介绍

    1.1 什么是备忘录模式

    备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式。

    备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。

    1.2 解决了什么问题

    通俗地说,备忘录模式就是一个对象的备份模式,提供了一种程序数据的备份方法。

    2 原理

    备忘录模式使用三个类 Memento、Originator 和 CareTaker。Memento 包含了要被恢复的对象的状态。Originator 创建并在 Memento 对象中存储状态。Caretaker 对象负责从 Memento 中恢复对象的状态。

    2.1 uml图

    image.png

    2.2 代码示例

    Memento代码示例

    public class Memento {
       private String state;
     
       public Memento(String state){
          this.state = state;
       }
     
       public String getState(){
          return state;
       }  
    }
    

    Originator代码示例

    public class Originator {
       private String state;
     
       public void setState(String state){
          this.state = state;
       }
     
       public String getState(){
          return state;
       }
     
       public Memento saveStateToMemento(){
          return new Memento(state);
       }
     
       public void getStateFromMemento(Memento Memento){
          state = Memento.getState();
       }
    }
    

    CareTaker代码示例

    public class CareTaker {
       private List<Memento> mementoList = new ArrayList<Memento>();
     
       public void add(Memento state){
          mementoList.add(state);
       }
     
       public Memento get(int index){
          return mementoList.get(index);
       }
    }
    

    调用示例

    public static void main(String[] args) {
          Originator originator = new Originator();
          CareTaker careTaker = new CareTaker();
          originator.setState("State #1");
          originator.setState("State #2");
          careTaker.add(originator.saveStateToMemento());
          originator.setState("State #3");
          careTaker.add(originator.saveStateToMemento());
          originator.setState("State #4");
     
          System.out.println("Current State: " + originator.getState());    
          originator.getStateFromMemento(careTaker.get(0));
          System.out.println("First saved State: " + originator.getState());
          originator.getStateFromMemento(careTaker.get(1));
          System.out.println("Second saved State: " + originator.getState());
       }
    

    运行结果

    Current State: State #4
    First saved State: State #2
    Second saved State: State #3
    

    2.3 优缺点

    3 适用场景

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

    数据库连接的事务管理就是用的备忘录模式,想想看,如果你要实现一个JDBC驱动,你怎么来实现事务?还不是用备忘录模式嘛!

    4 总结

    • 备忘录的生命期

    备忘录创建出来就要在“最近”的代码中使用,要主动管理它的生命周期,建立就要使用,不使用就要立刻删除其引用,等待垃圾回收器对它的回收处理。

    • 备忘录的性能

    不要在频繁建立备份的场景中使用备忘录模式(比如一个for循环中),原因有二:一是控制不了备忘录建立的对象数量;二是大对象的建立是要消耗资源的,系统的性能需要考虑。因此,如果出现这样的代码,设计师就应该好好想想怎么修改架构了。


    参考书籍及文章
    1.《Java与模式》,电子工业出版社,阎宏

    1. 《大话设计模式》,清华大学出版社,程杰
    2. 《设计模式——可复用面向对象软件的基础》,机械工业出版社,Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides
    3. 《Head First 设计模式(中文版)》,中国电力出版社
    4. 《图说设计模式》,https://design-patterns.readthedocs.io/zh_CN/latest/index.html

    相关文章

      网友评论

          本文标题:设计模式之十九——备忘录模式

          本文链接:https://www.haomeiwen.com/subject/eouucctx.html