设计模式之备忘录模式(Memento)

概念基础

  • 定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。
  • 场景:备份,恢复,工作流回退
  • 推导过程

1.被存储的对象(假设为Student) ,提供 store,recover 方法
2.保存的对象 => 引出StudentMemenTo(深浅clone根据业务)
3.需要有一个对象保存 StudentMemenTo的引用. =>引出 CareTaker
4.疑问:为什么要构建一个一样的新类,而不是直接返回一个新的clone对象 Student

  • 窄接口:负责人(Caretaker)对象(和其他除发起人之外的任何对象)看到的是备忘录的窄接口(narrow interface),这个窄接口只允许它把备忘录对象传给其他的对象。
  • 宽接口:与负责人对象看到的窄接口相反的是,发起人对象可以看到一个宽接口(wide interface),这个宽接口允许它读取所有的数据,以便根据这些数据恢复对这个发起人对象的内部状态。(限制手段 内部类+空接口,屏蔽负责人对象对备忘录的访问,仅仅作为一个传递作用)

Session 会话,就可以被当做负责人对象来使用, Spring 工作流中,有应用

public interface StateManageableMessageContext extends MessageContext {
    Serializable createMessagesMemento();

    void restoreMessages(Serializable var1);

    void setMessageSource(MessageSource var1);
}
image.png

优化,黑盒模式

  • 空接口+内部类 => 屏蔽看守者对备忘录的操作.(最少知道原则)
  • 发起人角色
package com.dzq.memento.dark;

public class Student {
    private int age ;
    private String name;
    /*保存*/
    public StudentMementoIf store(){
        return new StudentMemento(this);
    }
    /*恢复*/
    public void recover(StudentMementoIf stu){
        /*强制转化为备忘录对象*/
        StudentMemento student = (StudentMemento) stu;
        this.age = student.age;
        this.name = student.name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    /*内部类,仅仅Student本身能够访问*/
    protected class StudentMemento implements StudentMementoIf{
        private int age ;
        private String name;

        public StudentMemento(Student student) {
            this.age = student.age;
            this.name = student.name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }


}

  • 看守人实现(无法调用备忘录对象的方法)
package com.dzq.memento.dark;

import com.dzq.memento.PersonMemento;

import java.util.Vector;

/*看守人*/
public class CareTaker {
    private StudentMementoIf studentMementoIf;

    public StudentMementoIf getStudentMementoIf() {
        return studentMementoIf;
    }

    public void setStudentMementoIf(StudentMementoIf studentMementoIf) {
        this.studentMementoIf = studentMementoIf;
    }
}

  • 备忘录实现的空接口
package com.dzq.memento.dark;

/*空接口,用于屏蔽管理者对备份类的可见性*/
public interface StudentMementoIf {
}

优化二

  • 以上仅仅是简单状态属性,并且只能恢复到上一个节点.如果需要将状态恢复到第N次节点,如何实现?
  • 数组 + index ,可以做到恢复至某个具体的版本.
package com.dzq.memento.multi_check;

import java.util.Vector;
/**
 * 常见的软件系统往往存储不止一个状态,而是需要存储多个状态或者叫做有多个检查点
* */
public class Message {
    private Vector states;//核心  数组 + current_index
    private int index;

    public Vector getStates() {
        return states;
    }

    public void setStates(Vector states) {
        this.states = states;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }
}

你可能感兴趣的:(设计模式之备忘录模式(Memento))