1. 程式人生 > >重走Java設計模式——備忘錄模式(Memento Pattern)

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

備忘錄模式

定義

在不破壞封裝性的前提下,捕獲一個物件的內部狀態,並在該物件之外儲存這個狀態。

模式結構

  • 發起者角色(Originator):負責建立一個備忘錄用以記錄當前時刻它的內部狀態,並可以使用備忘錄恢復內部狀態;
  • 備忘錄角色(Memento):負責儲存Originator物件的內部狀態,並可以防止Originator以外的其他物件訪問備忘錄;
  • 管理者角色(CareTake):負責儲存好備忘錄。

程式碼示例

備忘錄模式使用三個類 MementoOriginatorCareTakerMemento 包含了要被恢復的物件的狀態。Originator 建立並在 Memento

物件中儲存狀態。Caretaker 物件負責從 Memento中恢復物件的狀態。 MementoPatternDemo,我們的演示類使用CareTakerOriginator 物件來顯示物件的狀態恢復。 在這裡插入圖片描述

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. 為了節約記憶體,可使用原型模式+備忘錄模式。