備忘錄模式

2022-09-07 00:30:28 字數 3217 閱讀 9440

**自  

上面所提到的就是「後悔藥」機制。在我們生活中,做錯事了我們都期望可以從新開始,希望這個世界上有後悔藥可以吃,但現實是殘酷的,這個世界是沒有後悔藥可以吃!雖然在現實社會中不可以實現,我們可以在軟體的世界裡實現(現在好多軟體有撤銷功能:ctrl+z不就是麼)。

在應用開發中,很多時候我們總是需要記錄乙個物件的內部狀態,這樣做的目的就是為了允許使用者取消不確定或者錯誤的操作,能夠恢復到他原先的狀態,使得他有「後悔藥」可吃。

備忘錄模式是一種給我們的軟體提供後悔藥的機制,通過它可以使系統恢復到某一特定的歷史狀態。

所謂備忘錄模式就是在不破壞封裝的前提下,捕獲乙個物件的內部狀態,並在該物件之外儲存這個狀態,這樣可以在以後將物件恢復到原先儲存的狀態。

備忘錄模式將要儲存的細節給封裝在備忘錄中,就是那天要改變儲存的細節也不會影響到客戶端。

下圖是備忘錄模式的uml結構圖:

備忘錄模式主要包含入下幾個角色:

originator: 原發器。負責建立乙個備忘錄,用以記錄當前物件的內部狀態,通過也可以使用它來利用備忘錄恢復內部狀態。同時原發器還可以根據需要決定memento儲存originator的那些內部狀態。

memento: 備忘錄。用於儲存originator的內部狀態,並且可以防止originator以外的物件訪問memento。在備忘錄memento中有兩個介面,其中caretaker只能看到備忘錄中的窄介面,它只能將備忘錄傳遞給其他物件。originator可以看到寬介面,允許它訪問返回到先前狀態的所有資料。

caretaker: 負責人。負責儲存好備忘錄,不能對備忘錄的內容進行操作和訪問,只能夠將備忘錄傳遞給其他物件。

在備忘錄模式中,最重要的就是備忘錄memento了。我們都是備忘錄中儲存的就是原發器的部分或者所有的狀態資訊,而這些狀態資訊是不能夠被其他物件所訪問了,也就是說我們是不可能在備忘錄之外的物件來儲存這些狀態資訊,如果暴漏了內部狀態資訊就違反了封裝的原則,故備忘錄是除了原發器外其他物件都是不可以訪問的。

所以為了實現備忘錄模式的封裝,我們需要對備忘錄的訪問做些控制:

對原發器:可以訪問備忘錄裡的所有資訊。

對負責人:不可以訪問備忘錄裡面的資料,但是他可以儲存備忘錄並且可以將備忘錄傳遞給其他物件。

其他物件:不可訪問也不可以儲存,它只負責接收從負責人那裡傳遞過來的備忘錄同時恢復原發器的狀態。

所以就備忘錄模式而言理想的情況就是只允許生成該備忘錄的那個原發器訪問備忘錄的內部狀態。

典型的備忘錄**如下:

class memento 

public void setstate(string state)

public string getstate()  

}

實現場景:我們就以遊戲挑戰boss為實現場景,在挑戰boss之前,角色的血量、藍量都是滿值,然後存檔,在大戰boss時,由於操作失誤導致血量和藍量大量損耗,所以只好恢復到剛剛開始的存檔點,繼續進行大戰boss了。這裡使用備忘錄模式來實現。uml結構圖如下:

首先是遊戲角色類:role.j**a

private int bloodflow;

private int magicpoint;

public role(int bloodflow,int magicpoint)

public int getbloodflow()

public void setbloodflow(int bloodflow)

public int getmagicpoint()

public void setmagicpoint(int magicpoint)

/*** @desc 展示角色當前狀態

* @return void

*/public void display()

/*** @desc 保持存檔、當前狀態

* @return

* @return memento

*/public memento s**ememento()

/*** @desc 恢復存檔

* @param memento

* @return void

*/public void restorememento(memento memento)

}

備忘錄:memento.j**a

class memento 

public void setbloodflow(int bloodflow)

public int getmagicpoint()

public void setmagicpoint(int magicpoint)

public memento(int bloodflow,int magicpoint)

}

負責人:caretaker.j**a

public class caretaker 

public void setmemento(memento memento)

}

客戶端:client.j**a

public class client 

}

執行結果

1、 給使用者提供了一種可以恢復狀態的機制。可以是使用者能夠比較方便地回到某個歷史的狀態。

2、 實現了資訊的封裝。使得使用者不需要關心狀態的儲存細節。

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

1、 需要儲存乙個物件在某乙個時刻的狀態或部分狀態。

2、 如果用乙個介面來讓其他物件得到這些狀態,將會暴露物件的實現細節並破壞物件的封裝性,乙個物件不希望外界直接訪問其內部狀態,通過負責人可以間接訪問其內部狀態。

1、 備忘錄模式可以實現在不破壞封裝的前提下,捕獲乙個類的內部狀態,並且在該物件之外儲存該物件的狀態,保證該物件能夠恢復到歷史的某個狀態。

2、 備忘錄模式實現了內部狀態的封裝,除了建立它的原發器之外其他物件都不能夠訪問它。

3、 備忘錄模式會占用較多的記憶體,消耗資源。

備忘錄模式

備忘錄模式 memento 在不破壞封裝性的前提下,捕獲乙個物件的內部狀態,並在該物件之外儲存這個狀態。這樣以後就可將該物件恢復到原先儲存的狀態。originator 發起人 負責建立乙個備忘錄memento,用以記錄當前時刻它的內部狀態,並可以使用備忘錄恢復內部狀態。originator可根據需要...

備忘錄模式

先從物件導向的三大特徵之一封裝說起。物件導向的封裝簡單點說就是把狀態 資料 和行為 操作這些資料的方法 放到一起,構成乙個單元,通常叫做類。乙個物件的行為是事先確定好的 靜態 一些指令碼,如果物件的狀態相同,物件看起來就是一樣的。所以當我們需要把乙個物件的某一時刻儲存起來,那麼只需要儲存它在那個時刻...

備忘錄模式

面臨問題 物件狀態的變化無端,如何回溯恢復物件在某個點的狀態?在軟體構建過程中,某些物件的狀態在轉換過程中,可能由於某種需要,要求程式能夠回溯到物件之前處於某個點時的狀態。如果使用一些公用介面來讓其他物件得到物件的狀態,便會暴露物件的細節實現。如何實現物件狀態的良好儲存與恢復?但同時又不會因此而破壞...