我的GitHub | 我的博客 | 我的微信 | 我的郵箱 |
---|---|---|---|
baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
備忘錄模式
簡介
在不破壞封裝的前提下,捕獲一個對象的【內部狀態】,並在該對象之外保存這個狀態,這樣以后就可以將該對象恢復到原先保存的狀態。
角色:
- 發起人Originator:要被備份的成員,它提供一創建備忘錄的方法,其實就是
將它自身的某些信息拷貝一份放到一個備忘錄對象中
。並提供另外一個方法將備忘錄中的信息覆蓋自身的信息。 - 備忘錄Memento:備忘錄對象中
包含存儲發起人狀態的成員變量
,它提供set,get或構造方法保存發起人狀態及獲取發起人狀態。 - 管理角色Caretaker:用於管理備忘錄對象的實現類。
適用場合:
- 它適用於對象在執行某些操作時,為防止意外,而在執行操作前,將對象狀態備份的場景,有點類似於【事務回滾】的意思。
- 功能比較復雜的,但是需要維護或記錄屬性歷史的類
- 需要保存的屬性只是眾多屬性的一小部分時
好處:
- 有時一些發起人對象的內部信息必須【保存在】發起人對象以外的地方,但是必須要由發起人對象自己讀取,這時使用備忘錄模式可以把復雜的發起人內部信息對其他的對象屏蔽起來,從而可以恰當地保持【封裝】的邊界
- 本模式【簡化】了發起人類。發起人不再需要管理和保存其內部狀態的一個個版本,客戶端可以自行管理他們所需要的這些狀態的版本
- 當發起人角色的狀態改變的時候,有可能這個狀態無效,這時候就可以使用暫時存儲起來的備忘錄將狀態復原
缺點:
- 如果發起人角色的狀態需要完整地存儲到備忘錄對象中,那么在【資源消耗】上面備忘錄對象會很昂貴
- 當負責人角色將一個備忘錄存儲起來的時候,負責人可能並不知道這個狀態會占用多大的存儲空間,從而無法提醒用戶一個操作是否很昂貴
案例
發起人Originator
要【被備份】的類
public class Originator {
public String date; //需要被保存的內部狀態
public int num; //需要被保存的內部狀態
//提供一個【創建備忘錄】的方法,其實就是將它自身的某些信息拷貝一份到一個備忘錄對象中
public Memento createMemento() {
return new Memento(this); //備忘錄持有當前對象的引用
}
public void setMemento(Memento memento) {
date = memento.date; //用備忘錄中的信息覆蓋自身信息
num = memento.num;
}
public void show() {
System.out.println(date + "---" + num);
}
}
備忘錄Memento
備忘錄對象中包含存儲發起人狀態的成員變量,它提供set,get或構造方法保存發起人狀態及獲取發起人狀態
public class Memento {
public String date;
public int num;
public Memento(Originator org) {
this.date = org.date;
this.num = org.num;
}
}
管理角色Caretaker
用於管理備忘錄對象。不能對備忘錄的內部進行操作或檢查
public class Caretaker {
private Memento memento;
public Memento getMemento() {
return this.memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
public class Test {
public static void main(String[] args) {
//原始數據
Originator org = new Originator();
org.date = new SimpleDateFormat("HH-mm-ss_SSS").format(new Date());
org.num = 99;
org.show();
//創建一個備忘錄對象,保存原始數據的狀態,目的是可以在需要時恢復
Memento memento = org.createMemento();
Caretaker ctk = new Caretaker(); //創建一個備忘錄管理類,用於管理備忘錄對象(其實基本沒什么卵用)
ctk.setMemento(memento);
//改變原始數據的狀態
org.date = new SimpleDateFormat("HH-mm-ss_SSS").format(new Date());
org.num = 100;
org.show();
//恢復之前保存的狀態(將保存的數據導入)
org.setMemento(ctk.getMemento());
org.show();
}
}
去除掉管理類
public class Test {
public static void main(String[] args) {
Originator org = new Originator();//原始數據
//...對原始數據進行各種操作
Memento memento = org.createMemento(); //創建一個備忘錄對象,保存原始數據的狀態,目的是可以在需要時恢復
//...改變原始數據的狀態
org.setMemento(memento);//恢復之前保存的狀態(將保存的數據導入)
org.show();
}
}
2016-04-20