###模式定義:數據庫
在不破環封裝行性的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態。這樣就能夠將該對象恢復到原先保存的狀態。 ###模式場景緩存
錄入大批人員資料的時候。正在錄入當前人資料時,發現上一我的錄錯了,此時須要恢復到上一我的的資料,進行修改。this
Word編輯時,突然斷電或電腦死機,再打開時,能夠看到Word提示你恢復到之前的文檔。code
###模式結構 對象
Memento:備忘錄。主要用來存儲原發器對象的內部狀態,可是具體須要存儲哪些數據是由原發器對象來決定的。另外備忘錄應該只能由原發器對象來訪問它內部的數據,原發器外部的對象不該該能訪問到備忘錄對象的內部數據。接口
Originator:原發器。使用備忘錄來保存某個時刻原發器自身的狀態,也可使用備忘錄來恢復內部狀態。遊戲
Caretaker:備忘錄管理者,或者稱爲備忘錄負責人。主要負責保存備忘錄對象,可是不能對備忘錄對象的內容進行操做或檢查。事務
###代碼實現 ####UML圖 ####源碼開發
public interface FlowAMockMemento { } public class FlowAMock { private String flowName; private int tempResult; private String tempState; public FlowAMock(String flowName) { this.flowName = flowName; } public void runPhaseOne(){ tempResult = 3; tempState = "phaseOne"; } public void schema1(){ this.tempState += ",Schema1"; System.out.println(this.tempState+":now run " + tempResult); this.tempResult += 11; } public void schema2(){ this.tempState += ",Schema2"; System.out.println(this.tempState+":now run " + tempResult); this.tempResult += 22; } public FlowAMockMemento createMemento(){ return new MementoImpl(this.tempResult,this.tempState); } public void setMemento(FlowAMockMemento memento){ MementoImpl mementoImpl = (MementoImpl) memento; this.tempResult = mementoImpl.getTempResult(); this.tempState = mementoImpl.getTempState(); } /** * 真正的備忘錄對象,實現備忘錄窄接口 * 實現成爲私有內部類 */ private static class MementoImpl implements FlowAMockMemento{ @Getter private int tempResult; @Getter private String tempState; public MementoImpl(int tempResult, String tempState) { this.tempResult = tempResult; this.tempState = tempState; } } } @Data public class FlowAMementoCareTaker{ private FlowAMockMemento memento; } public class Client { public static void main(String[] args) { FlowAMock mock = new FlowAMock("testFlow"); mock.runPhaseOne(); FlowAMementoCareTaker careTaker = new FlowAMementoCareTaker(); FlowAMockMemento memento = mock.createMemento(); careTaker.setMemento(memento); mock.schema1(); mock.setMemento(memento); mock.schema2(); } }
###模式的優缺點 ####模式的優勢文檔
更好的封裝性
備忘錄模式經過使用備忘錄對象,來封裝原發器對象的內部狀態,雖然這個對象是保存在原發器對象的外部,可是因爲備忘錄對象的窄接口並不提供任何方法,這樣有效的保證了對原發器對象內部狀態的封裝,不把原發器對象的內部實現細節暴露給外部。
簡化了原發器
備忘錄模式中,備忘錄對象被保存到原發器對象以外,讓客戶來管理他們請求的狀態,從而讓原發器對象獲得簡化。
窄接口和寬接口
####模式的缺點
可能會致使高開銷
備忘錄模式基本的功能,就是對備忘錄對象的存儲和恢復,它的基本實現方式就是緩存備忘錄對象。這樣一來,若是須要緩存的數據量很大,或者是特別頻繁的建立備忘錄對象,開銷是很大的。
###思考
模式本質:保存和恢復內部狀態
###開發中的應用場景:
棋類遊戲,悔棋
普通軟件,撤銷操做
數據庫軟件中的,事務管理的,回滾操做
Photoshop軟件
###相關模式
命令模式實現中,在實現命令的撤銷和重作的時候,可使用備忘錄模式,在命令操做的時候記錄下操做先後的狀態,而後在命令撤銷和重作的時候,直接使用相應的備忘錄對象來恢復狀態就能夠了。 在這種撤銷的執行順序和重作執行順序可控的狀況下,備忘錄對象還能夠採用增量式記錄的方式,能夠減小緩存的數據量。
在原發器對象建立備忘錄對象的時候,若是原發器對象中所有或者大部分的狀態都須要保存,一個簡潔的方式就是直接克隆一個原發器對象。也就是說,這個時候備忘錄對象裏面存放的是一個原發器對象的實例。