初識設計模式 – 備忘錄模式

簡介

備忘錄設計模式(Memento Design Pattern)也叫作快照(Snapshot)模式,主要用於實現防丟失、撤銷、恢復等功能。

其定義是,在不違背封裝原則的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態,以便之後恢復對象先前的狀態。

典型實現

首先,定義一個備忘錄 Memento 類存儲狀態,其代碼示例如下:

public class Memento {
    private String state;

    public Memento(Originator o) {
        this.state = o.getState();
    }

    public void setState(String State) {
        this.state = state;
    }

    public String getState() {
        return this.state;
    }
}

然後,把需要被存儲狀態的對象稱作為發起者,定義為 Originator 類,包含用於存儲成員數據的屬性,其代碼示例如下:

public class Originator {
    private String state;

    public Originator() {}

    // 創建一個備忘錄對象
    public Memento createMemento() {
        return new Memento(this);
    }

    // 根據備忘錄狀態恢復原發器狀態
    public void restoreMemento(Memento m) {
        state = m.getState();
    }

    public void setState(String State) {
        this.state = state;
    }

    public String getState() {
        return this.state;
    }
}

定義一個負責人 Caretaker 用於管理備忘錄對象,其代碼示例如下:

public class Caretaker {
    private Memento memento;

    public Memento getMemento() {
        return this.memento;
    }

    public void setMemento(Memento memento) {
        this.memento = memento;
    }
}

總結

優點

備忘錄模式的主要優點如下:

  • 給用戶提供了一種可以恢復狀態的機制,可以使用戶能夠比較方便地回到某個歷史的狀態
  • 實現了內部狀態的封裝,使得用戶不需要關心狀態的保存細節

缺點

備忘錄模式的主要缺點如下:

  • 如果要保存的內部狀態信息過多或者特別頻繁,將會佔用比較大的內存資源

適用場景

備忘錄模式的適用場景如下:

  • 保存一個對象在某一時刻的全部狀態或部分狀態,方便後續實現恢復和撤銷
  • 防止外界對象破壞一個對象歷史狀態的封裝性,避免將對象歷史狀態的實現細節暴露給外界對象

源碼

在 JDK 中 java.util.Date 通過自身內部的一個 Long 值來實現備忘錄模式。

如下是源碼部分:

public class Date implements java.io.Serializable, Cloneable, Comparable<Date> {
    private transient long fastTime;

    public Date(long date) {
        fastTime = date;
    }

    public long getTime() {
        return getTimeImpl();
    }

    private final long getTimeImpl() {
        if (cdate != null && !cdate.isNormalized()) {
            normalize();
        }
        return fastTime;
    }
}