天天看點

重走Java設計模式——備忘錄模式(Memento Pattern)

備忘錄模式

定義

在不破壞封裝性的前提下,捕獲一個對象的内部狀态,并在該對象之外儲存這個狀态。

模式結構

  • 發起者角色(Originator):負責建立一個備忘錄用以記錄目前時刻它的内部狀态,并可以使用備忘錄恢複内部狀态;
  • 備忘錄角色(Memento):負責存儲Originator對象的内部狀态,并可以防止Originator以外的其他對象通路備忘錄;
  • 管理者角色(CareTake):負責儲存好備忘錄。

代碼示例

備忘錄模式使用三個類

Memento

Originator

CareTaker

Memento

包含了要被恢複的對象的狀态。

Originator

建立并在

Memento

對象中存儲狀态。

Caretaker

對象負責從

Memento

中恢複對象的狀态。

MementoPatternDemo

,我們的示範類使用

CareTaker

Originator

對象來顯示對象的狀态恢複。

重走Java設計模式——備忘錄模式(Memento Pattern)

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
           

模式優缺點

優點

  1. 給使用者提供了一種可以恢複狀态的機制,可以使使用者能夠比較友善地回到某個曆史的狀态;
  2. 實作了資訊的封裝,使得使用者不需要關心狀态的儲存細節。

缺點

消耗資源。如果類的成員變量過多,勢必會占用比較大的資源,而且每一次儲存都會消耗一定的記憶體。

使用場景

  1. 需要儲存/恢複資料的相關狀态場景;
  2. 提供一個可復原的操作;

使用的注意事項

  1. 為了符合迪米特原則,還要增加一個管理備忘錄的類;
  2. 為了節約記憶體,可使用原型模式+備忘錄模式。