概念基础
- 定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。
- 场景:备份,恢复,工作流回退
- 推导过程
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 <STRONG>createMessagesMemento</STRONG>();
void<STRONG> restoreMessages</STRONG>(Serializable var1);
void<STRONG> setMessageSource</STRONG>(MessageSource var1);
}
优化,黑盒模式
- 空接口+内部类 => 屏蔽看守者对备忘录的操作.(最少知道原则)
- 发起人角色
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;
}
}