原文地址:折騰Java設計模式之備忘錄模式html
Without violating encapsulation, capture and externalize an object's internal state allowing the object to be restored to this state later.java
在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態。git
所謂備忘錄模式就是在不破壞封裝的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態,這樣能夠在之後將對象恢復到原先保存的狀態。不少時候咱們老是須要記錄一個對象的內部狀態,這樣作的目的就是爲了容許用戶取消不肯定或者錯誤的操做,可以恢復到他原先的狀態,使得他有"後悔藥"可吃。經過一個備忘錄類專門存儲對象狀態。客戶不與備忘錄類耦合,與備忘錄管理類耦合。github
Caretaker類是指用於保存(createMemento())和還原(restore(memento))發起方內部狀態的Originator類。 發起方類實現 (1)createMemento(),經過建立和返回存儲發起方當前內部狀態的memento對象 (2)經過從傳入的memento對象還原狀態來還原(memento)。設計模式
(1)保存發起人的內部狀態:Caretaker對Originator調用createMemento(),建立memento對象,保存其當前內部狀態(setState()),並將memento返回給Caretaker。微信
(2)恢復發起人的內部狀態:Caretaker對Originator調用restore(memento),並指定存儲應恢復狀態的memento對象。發起者從memento獲取狀態(getState())以設置其本身的狀態。this
(1) 備忘錄(Memento)角色:備忘錄角色存儲「備忘發起角色」的內部狀態。「備忘發起角色」根據須要決定備忘錄角色存儲「備忘發起角色」的哪些內部狀態。爲了防止「備忘發起角色」之外的其餘對象訪問備忘錄。備忘錄實際上有兩個接口,「備忘錄管理者角色」只能看到備忘錄提供的窄接口——對於備忘錄角色中存放的屬性是不可見的。「備忘發起角色」則可以看到一個寬接口——可以獲得本身放入備忘錄角色中屬性。設計
(2) 備忘發起(Originator)角色:「備忘發起角色」建立一個備忘錄,用以記錄當前時刻它的內部狀態。在須要時使用備忘錄恢復內部狀態。rest
(3) 備忘錄管理者(Caretaker)角色:負責保存好備忘錄。不能對備忘錄的內容進行操做或檢查。code
public class Caretaker { public static void main(String[] args) { List<Memento> savedStates = new ArrayList(); Originator originator = new Originator(); originator.set("State1"); originator.set("State2"); savedStates.add(originator.saveToMemento()); originator.set("State3"); savedStates.add(originator.saveToMemento()); originator.set("State4"); originator.restoreFromMemento(savedStates.get(1)); } } @Slf4j public class Originator { private String state; //狀態更改 public void set(String state) { this.state = state; log.info("Originator: Setting state to {}", state); } //將狀態保存到備忘錄裏 public Memento saveToMemento() { log.info("Originator: Saving to Memento."); return new Memento(this.state); } //從備忘錄裏取出狀態並回滾 public void restoreFromMemento(Memento memento) { this.state = memento.getState(); log.info("Originator: State after restoring from Memento: {}", state); } } @Data @AllArgsConstructor public class Memento { //狀態維護 private String state; }
示例結果
從上述代碼中看的出,隨着狀態變動,用List維護髮起者的狀態列表,從備忘錄中取出狀態以便回退狀態。
生成對象狀態的一個快照,以便對象能夠恢復原始狀態而不用暴露自身的內容。Date對象經過自身內部的一個long值來實現備忘錄模式。
java.util.Date
java.io.Serializable
一、給用戶提供了一種能夠恢復狀態的機制,可使用戶可以比較方便地回到某個歷史的狀態。 二、實現了信息的封裝,使得用戶不須要關心狀態的保存細節。
消耗資源。若是類的成員變量過多,勢必會佔用比較大的資源,並且每一次保存都會消耗必定的內存。
一、須要保存/恢復數據的相關狀態場景。 二、提供一個可回滾的操做。
一、爲了符合迪米特原則,還要增長一個管理備忘錄的類。 二、爲了節約內存,可以使用原型模式+備忘錄模式。
歡迎關注