備忘錄模式:在不破壞封閉的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態。這樣之後就可將該對象恢復到原先保存的狀態。java
涉及角色:測試
1.Originator(發起人):負責建立一個備忘錄Memento,用以記錄當前時刻自身的內部狀態,並可以使用備忘錄恢復內部狀態。Originator能夠根據須要決定Memento存儲本身的哪些內部狀態。this
2.Memento(備忘錄):負責存儲Originator對象的內部狀態,並能夠防止Originator之外的其餘對象訪問備忘錄。備忘錄有兩個接口:Caretaker只能看到備忘錄的窄接口,他只能將備忘錄傳遞給其餘對象。Originator卻可看到備忘錄的寬接口,容許它訪問返回到先前狀態所須要的全部數據。spa
3.Caretaker(管理者):負責備忘錄Memento,不能對Memento的內容進行訪問或者操做。3d
關於寬窄接口,java中有三種實現code
第一種就是採用兩個不一樣的接口類來限制訪問權限。這兩個接口類中,一個提供比較完備的操做狀態的方法,咱們稱它爲寬接口;而另外一個則能夠只是一個標示,咱們稱它爲窄接口。備忘錄角色要實現這兩個接口類。這樣對於「備忘發起角色」採用寬接口進行訪問,而對於其餘的角色或者對象則採用窄接口進行訪問。這種實現比較簡單,可是須要人爲的進行規範約束——而這每每是沒有力度的。對象
第二種方法便很好的解決了第一種的缺陷:採用內部類來控制訪問權限。將備忘錄角色做爲「備忘發起角色」的一個私有內部類。blog
第三種方式是不太推薦使用的:使用clone方法來簡化備忘錄模式。因爲Java提供了clone機制,這使得複製一個對象變得輕鬆起來。使用了clone機制的備忘錄模式,備忘錄角色基本能夠省略了,並且能夠很好的保持對象的封裝。可是在爲你的類實現clone方法時要慎重啊。接口
我的比較推薦第二種方式,這也是許多開源項目使用的方式,下面是在網上找的一個類圖資源
demo以下:
發起者和備忘錄,備忘錄類爲發起者的一個內部類
package memento; public class Hero { private Integer bloodVolume; private Integer magicPoint; public Hero(Integer bloodVolume,Integer magicPoint) { this.bloodVolume = bloodVolume; this.magicPoint = magicPoint; } public void show() { System.out.println("bloodVolume:" +bloodVolume +",magicPoint" + magicPoint); } public StatusMemento saveStatus() { return new StatusMemento(bloodVolume,magicPoint); } public void fight() { this.bloodVolume -=5; this.magicPoint=0; } public void recover(MementoInterface mementoInterface) { StatusMemento sm = (StatusMemento)mementoInterface; this.bloodVolume = sm.bloodVolume; this.magicPoint = sm.magicPoint; } private class StatusMemento implements MementoInterface{ private Integer bloodVolume; private Integer magicPoint; StatusMemento(Integer bloodVolume,Integer magicPoint){ this.bloodVolume = bloodVolume; this.magicPoint = magicPoint; } } }
接口標識類,方便咱們在類外部訪問其局部內部類
package memento; public interface MementoInterface { }
管理者類
package memento; public class MementoManager { private MementoInterface memento; public MementoInterface getMemento() { return memento; } public void setMemento(MementoInterface memento) { this.memento = memento; } }
測試代碼及執行結果
備忘錄模式的優勢
一、有時一些發起人對象的內部信息必須保存在發起人對象之外的地方,可是必需要由發起人對象本身讀取,這時,使用備忘錄模式能夠把複雜的發起人內部信息對其餘的對象屏蔽起來,從而能夠恰當地保持封裝的邊界。
二、本模式簡化了發起人類。發起人再也不須要管理和保存其內部狀態的一個個版本,客戶端能夠自行管理他們所須要的這些狀態的版本。
三、當發起人角色的狀態改變的時候,有可能這個狀態無效,這時候就能夠使用暫時存儲起來的備忘錄將狀態復原。
備忘錄模式的缺點:
一、若是發起人角色的狀態須要完整地存儲到備忘錄對象中,那麼在資源消耗上面備忘錄對象會很昂貴。
二、當負責人角色將一個備忘錄 存儲起來的時候,負責人可能並不知道這個狀態會佔用多大的存儲空間,從而沒法提醒用戶一個操做是否很昂貴。
三、當發起人角色的狀態改變的時候,有可能這個協議無效。若是狀態改變的成功率不高的話,不如採起「假如」協議模式。