java設計模式---備忘錄模式
備忘錄模式
-
概述:在不破壞封裝性的前提下,捕獲一個物件的內部狀態,並在該物件之外儲存這個狀態.這樣可以將物件恢復到原先儲存的狀態.
-
幫助理解:備忘錄模式就是為物件提供一個備份的地方,當物件想要回滾到前一個狀態時,呼叫備忘錄物件直接就可以恢復.
-
備忘錄模式說包含的角色
-
Originator : 原發器,也就是發起者.記錄有當前時刻自身的內部狀態,負責建立一個備忘錄Memento,用於記錄當前時刻自身的內部狀態,並可使用備忘錄恢復內部狀態.Originator可以根據需要決定Memento儲存自己的哪些內部狀態(發起者可能有很多內部狀態,可以決定哪些由備忘錄備份)
-
Memento : 備忘錄.負責儲存Originator物件的內部狀態,並可以防止Originator之外的其它物件訪問備忘錄.備忘錄有兩個介面.Caretaker只能看到備忘錄的窄介面,他只能將備忘錄物件傳遞給其它物件.Originator卻能夠看到備忘錄的寬介面.允許它訪問返回到先前狀態所需要的所有資料.
-
Caretaker : 管理者.負責儲存備忘錄.但是不能對備忘錄的內容進行操作和訪問.只能夠將備忘錄傳遞給其它物件.
-
-
優點
-
有時一些發起人物件的內部資訊必須儲存在發起人物件以外的地方,但是必須由發起人物件自己讀取.這時使用備忘錄模式可以將複雜的發起人內部資訊對其它物件遮蔽起來.從而可以恰當的保持封裝的邊界.
-
備忘錄模式簡化了發起者類.發起者不再需要管理和儲存其內部狀態的一個個版本.客戶端可以自行管理他們所需要的這些狀態的版本.
-
當發起者角色的狀態發生改變的時候.有可能這個狀態無效,需要回滾到前一個狀態.這時候可以使用暫時儲存起來的備忘錄將狀態進行還原.
-
-
缺點
-
如果發起者角色的狀態有很多並且需要完整的儲存到備忘錄物件中.那麼備忘錄物件會很消耗資源.
-
-
注意事項
-
備忘錄模式最理想的情況是隻允許生成該備忘錄的那個原發器能夠訪問這個備忘錄的內部狀態.
-
/** * 〈備忘錄物件類〉 * * @author vegetate * @create 2018/11/12 17:08 */ public class MemoBean { private int useTime;//使用時間 private String deviceName;//裝置名稱 private int stateLevel;//狀態 public int getUseTime() { return useTime; } public void setUseTime(int useTime) { this.useTime = useTime; } public String getDeviceName() { return deviceName; } public void setDeviceName(String deviceName) { this.deviceName = deviceName; } public int getStateLevel() { return stateLevel; } public void setStateLevel(int stateLevel) { this.stateLevel = stateLevel; } }
/**
* 〈備忘錄管理物件〉
*
* @author vegetate
* @create 2018/11/12 17:11
*/
public class MemoManager {
MemoBean memento;
public MemoBean getMemento() {
return memento;
}
public void setMemento(MemoBean memento) {
this.memento = memento;
}
}
/**
* 〈發起者物件〉
*
* @author vegetate
* @create 2018/11/12 17:13
*/
public class MemoRole {
private int useTime;// 使用時間
private String deviceName;// 裝置名稱
private int stateLevel;// 狀態
public MemoRole(String deviceName, int useTime, int stateLevel) {
super();
this.useTime = useTime;
this.deviceName = deviceName;
this.stateLevel = stateLevel;
}
public MemoRole() {
}
public int getUseTime() {
return useTime;
}
public void setUseTime(int useTime) {
this.useTime = useTime;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public int getStateLevel() {
return stateLevel;
}
public void setStateLevel(int stateLevel) {
this.stateLevel = stateLevel;
}
public MemoBean createMemoObject() {
MemoBean memento = new MemoBean();
memento.setDeviceName(deviceName);
memento.setStateLevel(stateLevel);
memento.setUseTime(useTime);
return memento;
}
public void setMemento(MemoBean memento) {
this.deviceName = memento.getDeviceName();
this.stateLevel = memento.getStateLevel();
this.useTime = memento.getUseTime();
}
/**
* 獲取物件當前狀態
*/
public void getCurrentState() {
System.out.println("當前裝置名稱:" + this.deviceName + "當前使用時間:" + this.useTime + "當前工作狀態:" + this.stateLevel);
}
}
測試類
/**
* 〈測試類〉
*
* @author vegetate
* @create 2018/11/12 17:14
*/
public class Test {
public static void main(String[] args) {
// 新建備忘錄發起者物件
MemoRole role = new MemoRole("發電機", 0, 1);
// 新建備忘錄管理者
MemoManager manager = new MemoManager();
// 角色初始狀態
System.out.println("機器開始發電:");
role.getCurrentState();
// 利用備忘錄模式儲存當前狀態
System.out.println("---儲存當前的機器狀態---");
manager.setMemento(role.createMemoObject());
role.setDeviceName("發電機");
role.setStateLevel(5);
role.setUseTime(1000);
System.out.println("已經持續發電1000小時");
role.getCurrentState();
// 恢復儲存的角色狀態
role.setMemento(manager.getMemento());
System.out.println("恢復後發電機當前狀態:");
role.getCurrentState();
}
}
結果:
機器開始發電:
當前裝置名稱:發電機當前使用時間:0 當前工作狀態:1
—儲存當前的機器狀態—
已經持續發電N小時
當前裝置名稱:發電機當前使用時間:1000 當前工作狀態:5
恢復後發電機當前狀態:
當前裝置名稱:發電機當前使用時間:0 當前工作狀態1