概念基礎(chǔ)
- 定義:在不破壞封裝性的前提下,捕獲一個(gè)對象的內(nèi)部狀態(tài),并在該對象之外保存這個(gè)狀態(tài),以便以后當(dāng)需要時(shí)能將該對象恢復(fù)到原先保存的狀態(tài)。該模式又叫快照模式。
- 場景:備份,恢復(fù),工作流回退
- 推導(dǎo)過程
1.被存儲(chǔ)的對象(假設(shè)為Student) ,提供 store,recover 方法
2.保存的對象 => 引出StudentMemenTo(深淺clone根據(jù)業(yè)務(wù))
3.需要有一個(gè)對象保存 StudentMemenTo的引用. =>引出 CareTaker
4.疑問:為什么要構(gòu)建一個(gè)一樣的新類,而不是直接返回一個(gè)新的clone對象 Student
- 窄接口:負(fù)責(zé)人(Caretaker)對象(和其他除發(fā)起人之外的任何對象)看到的是備忘錄的窄接口(narrow interface),這個(gè)窄接口只允許它把備忘錄對象傳給其他的對象。
- 寬接口:與負(fù)責(zé)人對象看到的窄接口相反的是,發(fā)起人對象可以看到一個(gè)寬接口(wide interface),這個(gè)寬接口允許它讀取所有的數(shù)據(jù),以便根據(jù)這些數(shù)據(jù)恢復(fù)對這個(gè)發(fā)起人對象的內(nèi)部狀態(tài)。(限制手段 內(nèi)部類+空接口,屏蔽負(fù)責(zé)人對象對備忘錄的訪問,僅僅作為一個(gè)傳遞作用)
Session 會(huì)話,就可以被當(dāng)做負(fù)責(zé)人對象來使用, Spring 工作流中,有應(yīng)用
public interface StateManageableMessageContext extends MessageContext {
Serializable <STRONG>createMessagesMemento</STRONG>();
void<STRONG> restoreMessages</STRONG>(Serializable var1);
void<STRONG> setMessageSource</STRONG>(MessageSource var1);
}

image.png
優(yōu)化,黑盒模式
- 空接口+內(nèi)部類 => 屏蔽看守者對備忘錄的操作.(最少知道原則)
- 發(fā)起人角色
package com.dzq.memento.dark;
public class Student {
private int age ;
private String name;
/*保存*/
public StudentMementoIf store(){
return new StudentMemento(this);
}
/*恢復(fù)*/
public void recover(StudentMementoIf stu){
/*強(qiáng)制轉(zhuǎn)化為備忘錄對象*/
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;
}
/*內(nèi)部類,僅僅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;
}
}
}
- 看守人實(shí)現(xiàn)(無法調(diào)用備忘錄對象的方法)
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;
}
}
- 備忘錄實(shí)現(xiàn)的空接口
package com.dzq.memento.dark;
/*空接口,用于屏蔽管理者對備份類的可見性*/
public interface StudentMementoIf {
}
優(yōu)化二
- 以上僅僅是簡單狀態(tài)屬性,并且只能恢復(fù)到上一個(gè)節(jié)點(diǎn).如果需要將狀態(tài)恢復(fù)到第N次節(jié)點(diǎn),如何實(shí)現(xiàn)?
- 數(shù)組 + index ,可以做到恢復(fù)至某個(gè)具體的版本.
package com.dzq.memento.multi_check;
import java.util.Vector;
/**
* 常見的軟件系統(tǒng)往往存儲(chǔ)不止一個(gè)狀態(tài),而是需要存儲(chǔ)多個(gè)狀態(tài)或者叫做有多個(gè)檢查點(diǎn)
* */
public class Message {
private Vector states;//核心 數(shù)組 + 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;
}
}