• 设计模式之备忘录模式


    一、备忘录模式

      备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。

    在这里插入图片描述

    • 原发器(Originator)角色:原发器根据需要决定将自己的哪些内部状态保存到备忘录中,并可以使用备忘录来恢复内部状态。

    • 备忘录(Memento)角色:负责存储原发器对象的内部状态,但是具体需要存储哪些状态是由原发器对象来决定的。另外备忘录应该只能由原发器对象来访问它内部的数据,原发器外部的对象不应该访问到备忘录对象的内部数据。为了控制对备忘录对象的访问,备忘录模式中出现了窄接口和宽接口的概念。

      • 窄接口:管理者只能看到备忘录的窄接口,窄接口的实现中通常没有任何的方法,只是一个类型标识。窄接口使得管理者只能将备忘录传递给其他对象。
      • 宽接口:原发器能够看到备忘录的宽接口,从而可以从备忘录中获取到所需的数据,来将自己恢复到备忘录中所保存的状态。理想情况是:只允许生成备忘录的原发器来访问该备忘录的内部状态,通常实现成为原发器内的一个私有内部类。
    • 管理者(Caretaker)角色:备忘录管理者,或者称为备忘录负责人。主要负责保存好备忘录对象,但是不能对备忘录对象的内容进行操作或检查。

    二、备忘录模式实现方式

    1、备忘录角色

    //宽接口
    public class Memento {
    
       private String state;
     
       public Memento(String state){
          this.state = state;
       }
     
       public String getState(){
          return state;
       }  
    }
    
    //窄接口
    public interface Memento {
     
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2、原发器角色

    //宽接口
    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();
       }
    }
    
    //窄接口
    public class Originator {
       private String state;
     
       public void setState(String state){
          this.state = state;
       }
     
       public String getState(){
          return state;
       }
     
       public Memento saveStateToMemento(){
          return new MementoImpl(state);
       }
     
       public void getStateFromMemento(Memento Memento){
       	  MementoImpl mementoImpl = (MementoImpl) memento;
          state = Memento.getState();
       }
       /**
         * 真正的备忘录对象,实现了备忘录窄接口 实现成私有的内部类,不让外部访问
         */
        private static class MementoImpl implements  Memento {
            private String state;
    
            public MementoImpl(String state) {
                super();
                this.state = state;
            }
    
            public String getState() {
                return state;
            }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    3、管理者角色

    对备忘录进行管理、保存和提供备忘录,只能将备忘录传递给其他角色

    public class CareTaker {
       private List<Memento> mementoList = new ArrayList<>();
     
       public void add(Memento state){
          mementoList.add(state);
       }
     
       public Memento get(int index){
          return mementoList.get(index);
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4、测试

    public class MementoPatternDemo {
       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());
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    结果

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

    三、备忘录模式总结

    优点

    • 状态恢复机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。
    • 信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动。备忘录保存了原发器的状态,采用列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。

    缺点

    • 如果需要保存的状态过多时,每一次保存都会消耗很多内存(所以可以结合原型模式使用)。

    使用场景

    • 需要保存和恢复数据的相关场景;
    • 提供一个可回滚的操作,如ctrl+z、浏览器回退按钮、Backspace键等;
    • 需要监控的副本场景;
  • 相关阅读:
    SpringBoot 02 自动装配原理和启动类
    金九银十进大厂必刷的105道Java面试题(不得不说的秘密)
    安装使用electron
    从无人机到实景三维海洋系统
    怎样用Python识别条形码?
    一个.Net开发的轻量级SQLite数据库ORM
    短视频矩阵系统源头开发
    转载csdn文章操作
    windows上运行qemu仿真stm32板子a9板子实例
    SpringBoot 中使用 RabbitTemplate
  • 原文地址:https://blog.csdn.net/qq_42764269/article/details/127390470