備忘錄模式
定義
在不破壞封裝性的前提下,捕獲一個對象的内部狀态,并在該對象之外儲存這個狀态。
模式結構
- 發起者角色(Originator):負責建立一個備忘錄用以記錄目前時刻它的内部狀态,并可以使用備忘錄恢複内部狀态;
- 備忘錄角色(Memento):負責存儲Originator對象的内部狀态,并可以防止Originator以外的其他對象通路備忘錄;
- 管理者角色(CareTake):負責儲存好備忘錄。
代碼示例
備忘錄模式使用三個類
Memento
、
Originator
和
CareTaker
。
Memento
包含了要被恢複的對象的狀态。
Originator
建立并在
Memento
對象中存儲狀态。
Caretaker
對象負責從
Memento
中恢複對象的狀态。
MementoPatternDemo
,我們的示範類使用
CareTaker
和
Originator
對象來顯示對象的狀态恢複。
1.建立 Memento 類
Memento.java
public class Memento {
private String state;
public Memento(String state){
this.state = state;
}
public String getState(){
return state;
}
}
2.建立 Originator 類
Originator.java
public class Originator {
private String state;
public void setState(String state){
this.state = state;
}
public String getState(){
return state;
}
public Memento saveStateToMemento(){
return new Memento(state);
}
public void getStateFromMemento(Memento Memento){
state = Memento.getState();
}
}
3.建立 CareTaker 類
CareTaker.java
import java.util.ArrayList;
import java.util.List;
public class CareTaker {
private List<Memento> mementoList = new ArrayList<Memento>();
public void add(Memento state){
mementoList.add(state);
}
public Memento get(int index){
return mementoList.get(index);
}
}
4.使用 CareTaker 和 Originator 對象
public class MementoPatternDemo {
public static void main(String[] args) {
Originator originator = new Originator();
CareTaker careTaker = new CareTaker();
originator.setState("State #1");
originator.setState("State #2");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #3");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #4");
System.out.println("Current State: " + originator.getState());
originator.getStateFromMemento(careTaker.get(0));
System.out.println("First saved State: " + originator.getState());
originator.getStateFromMemento(careTaker.get(1));
System.out.println("Second saved State: " + originator.getState());
}
}
5.驗證輸出
Current State: State #4
First saved State: State #2
Second saved State: State #3
模式優缺點
優點
- 給使用者提供了一種可以恢複狀态的機制,可以使使用者能夠比較友善地回到某個曆史的狀态;
- 實作了資訊的封裝,使得使用者不需要關心狀态的儲存細節。
缺點
消耗資源。如果類的成員變量過多,勢必會占用比較大的資源,而且每一次儲存都會消耗一定的記憶體。
使用場景
- 需要儲存/恢複資料的相關狀态場景;
- 提供一個可復原的操作;
使用的注意事項
- 為了符合迪米特原則,還要增加一個管理備忘錄的類;
- 為了節約記憶體,可使用原型模式+備忘錄模式。