天天看點

設計模式-備忘錄模式

  備忘錄(Memonto)模式又叫做快照模式(Snapshot Pattern)或Token模式,是對象的行為模式。 (學習)

  備忘錄對象是一個用來存儲另外一個對象内部狀态的快照的對象。備忘錄模式的用意是在不破壞封裝的條件下,将一個對象的狀态捕捉(Capture)住,并外部化,存儲起來,進而可以在将來合适的時候把這個對象還原到存儲起來的狀态。備忘錄模式常常與指令模式和疊代子模式一同使用。

備忘錄模式的結構

備忘錄模式所涉及的角色有三個:備忘錄(Memento)角色、發起人(Originator)角色、負責人(Caretaker)角色。

備忘錄角色

備忘錄角色有如查責任:

  1. 将發起人(Originator)對象的内戰狀态存儲起來。備忘錄可以根據發起人對象的判斷來決定存儲多少發起人(Originator)對象的記憶體狀态。
  2. 備忘錄可以保護其内容不被發起人(Originator)對象之外的任何對象所讀取。

備忘錄有兩個等效的接口:

  • 窄接口:負責人(Caretaker)對象(和其他除發起人對象之外的任何對象)看到的是備忘錄的窄接口(narrow interface),這個窄接口隻允許它把備忘錄對象傳給其它的對象。
  • 寬接口:與負責人對象看到的窄接口相反的是,發起人對象可以看到一個寬接口(wide interface),這個寬接口允許它讀取所有的資料,以便根據這些資料恢複這個發起人對象的内部狀态。

發起人角色

發起人角色有如下責任:

  1. 建立一個含有目前的内部狀态的備忘錄對象。
  2. 使用備忘錄對象存儲其内部狀态。

負責人角色

負責人角色有如下責任:

  1. 負責儲存備忘錄對象。
  2. 不檢查備忘對象的内容。

“白箱”備忘錄模式的實作

  備忘錄角色對任何對象都提供一個接口,即寬接口,備忘錄角色的内部所存儲的狀态就對所有對象公開。是以這個實作又叫做“白箱實作”。

  “白箱”實作将發起人角色的狀态存儲在一個大家都看得到的地方上,是以是破壞封裝性的。但是通過程式員自律,同樣可以在一定程度上實作模式的大部分用意。是以白箱實作仍然是有意義的。

  下面給出一個示意性的“白箱實作”。

源代碼

package Memento.WhiteBox

/**
 * 發起人角色類,發起人角色利用一個新建立的備忘錄對象将自已的内部狀态存儲起來
 * */
class Originator {

    var state = ""
        set(value) {
            field = value
            //println("目前狀态:$field")
        }

    /**
     * 工廠方法,傳回一個新的備忘錄對象
     * */
    fun createMemento(): Memento {
        return Memento(state)
    }

    /**
     * 将發起人恢複到備忘錄對象所記載的狀态
     * */
    fun restoreMemento(memento: Memento) {
        this.state = memento.state
    }
}      
package Memento.WhiteBox

/**
 * 備忘錄角色類,備忘錄對象将發起人對象傳入的狀态存儲起來
 * */
class Memento constructor(state: String) {

    var state = ""

    init {
        this.state = state
    }
}      
package Memento.WhiteBox

/**
 * 負責人角色類,負責人角色負責儲存備忘錄對象,但是從不修改(甚至不檢視)備忘錄對象的内容
 * */
class Caretaker {

    private var memento: Memento? = null

    /**
     * 備忘錄的取值方法
     * */
    fun rerieveMemento(): Memento {
        if (memento == null) {
            memento = Memento("")
        }
        return memento!!
    }

    /**
     * 備忘錄的指派方法
     * */
    fun saveMemento(memento: Memento) {
        this.memento = memento
    }
}      

測試

val originator = Originator()
val caretaker = Caretaker()
//改變負責人對象的狀态
originator.state = "on"
//建立備忘錄對象,并将發起人對象的狀态儲存起來
caretaker.saveMemento(originator.createMemento())
//修改發起人的狀态
originator.state = "off"
//恢複發起人對象的狀态
originator.restoreMemento(caretaker.rerieveMemento())
println(originator.state)      

  在上面的這個示意性的例子裡,首先将發起人對象的狀态設定成"on",并建立一個備忘錄對象将這個狀态存儲起來;然後将發起人對象的狀态修改成"off";最後又将發起人對象恢複到備忘錄對象所存儲起來的狀态,即"on"狀态。

繼續閱讀