Java設計模式之備忘錄模式
一、介紹
備忘錄模式(Memento Pattern),屬于行為型設計模式。目的是用于保存一個對象在某一時刻的狀態(tài),以便于在將來某個時刻根據(jù)此狀態(tài)恢復該對象。
在我們日常生活中,備忘錄的使用十分頻繁。比如,有一個事情我們完成了35%的進度,這時有另一件更重要的事情需要處理,那么我們需要對這個已完成35%的事情進行記錄(做了哪些事情,做到什么程度等),當那個更重要的事情完成后,就可以根據(jù)記錄的內容(做了哪些事情,做到什么程度等)繼續(xù)處理這件事情,而不至于因為忘記處理進度而導致重復或疏漏,這個記錄的過程就是備忘。
另一個十分鮮活的例子就是,我們經常在對一些東西進行計數(shù)時被其他人說話而打斷,當你回答對方后自己卻突然忘記數(shù)到哪里了,如果你在說話前已經數(shù)了相當長一段時間,那此時你可能不得不從0重新開始計數(shù)。當應用備忘錄時,無論你的計數(shù)達到什么程度,在別人和你說話時,你先將當前計數(shù)保存記錄下來,在談話完成后,再繼續(xù)計數(shù)即可,以此避免從0重新開始計數(shù)。
當我們系統(tǒng)中存在一個對象,
下面是備忘錄模式的概念解釋:
在不破壞封裝性的前提下,捕獲一個對象的內部狀態(tài),并在該對象之外保存這個狀態(tài)。
二、應用舉例
根據(jù)我們在介紹中的描述,我們應該明白了備忘錄模式的本質其實就是對象狀態(tài)的保存和讀取。不難發(fā)現(xiàn),備忘錄模式的應用到處可見
幾乎所有的軟件
在我們使用的所有軟件無論是桌面端還是網頁端,只要有保存功能,就都是備忘錄模式的體現(xiàn)。
比如,我們使用txt文本文檔編輯文本,在編輯的過程中任意時刻我們都可以使用ctrl+s對其保存,當再次打開該txt文檔時,展示的就是我們最后一次保存時的文本,這種備忘的介質就是硬盤。
再比如,我們在某一個網站中對個人信息進行編輯時,當按下保存按鈕時,網頁會發(fā)起網絡請求,將我們編輯的個人信息發(fā)送到遠程服務器,當再次打開個人信息頁面進行查看或編輯時,網頁會再次向遠程服務器發(fā)起請求獲取我們上一次保存?zhèn)€人信息。這種備忘的介質就是遠程數(shù)據(jù)庫。
java序列化
java的序列化和反序列化過程也是備忘錄模式的體現(xiàn)。其中,序列化的過程就相當于對一個對象狀態(tài)的保存,反序列化的過程就相當于對以保存的對象狀態(tài)進行恢復。
三、基本角色
在標準的備忘錄模式中,包含以下三個角色:
Memento
保存對象的內部狀態(tài)。即備忘錄本身。而既然是備忘錄,自然有兩個最基本的方法來保存和獲取其內部保存的狀態(tài):getState()和setState()。
存儲源發(fā)器對象的狀態(tài)。備忘錄對象可以包括一個或多個狀態(tài)屬性,源發(fā)器可以根據(jù)需要保存和恢復狀態(tài)。
Originator
創(chuàng)建備忘錄,并保存指定對象的狀態(tài)。即備忘錄管理者。作為備忘錄的管理者,自然在其內部保存著多個備忘(mementoList)和對應的添加刪除方法(add(memento)和remove(memento))。
需要保存和恢復狀態(tài)的對象。它創(chuàng)建一個備忘錄對象,用于存儲當前對象的狀態(tài),也可以使用備忘錄對象恢復自身的狀態(tài)。
Caretaker
從備忘錄中讀取對象的狀態(tài)并恢復對象。有了備忘錄管理者,我們對備忘錄的操作應轉移到管理者上,通過備忘錄管理者存取備忘錄中的狀態(tài)。
負責保存?zhèn)渫泴ο?,但不能修改備忘錄對象的內容。它可以存儲多個備忘錄對象,并決定何時將備忘錄恢復給源發(fā)器。
注意:一般情況下,備忘錄模式無需抽象組件,但究竟需不需要抽象類根據(jù)實際情況來定。
備忘錄的通用UML圖如下所示

四、代碼演示
下面我們通過代碼對上面基本角色的分析進行演示
備忘錄類Memento
public class Memento {
// 對象某一時刻的狀態(tài)
private String state;
// 獲取對象的狀態(tài)
public String getState() {
return state;
}
// 保存對象的狀態(tài)
public void setState(String state) {
this.state = state;
}
}備忘錄管理員類Originator
public class Originator {
// 備忘錄集合
private final List<Memento> mementoList;
public Originator() {
// 對備忘錄集合進行初始化
this.mementoList = new ArrayList<>();
}
// 保存對象某一狀態(tài)到備忘錄
public void saveState(String state) {
Memento memento = new Memento();
memento.setState(state);
mementoList.add(memento);
}
// 獲取某一備忘錄并將其移除
public Memento getMemento(int index) {
return mementoList.remove(index);
}
}讀取狀態(tài)類Caretaker
public class Caretaker {
// 備忘錄管理者
private final Originator originator;
// 備忘錄管理者的初始化
public Caretaker(Originator originator) {
this.originator = originator;
}
// 獲取某個備忘錄中對象的狀態(tài)
public String getState(Integer index) {
return originator.getMemento(index).getState();
}
}客戶端測試代碼
public class MementoDemo {
public static void main(String[] args) {
// 將對象的狀態(tài)交給備忘錄管理員通過備忘錄管理
Originator originator = new Originator();
originator.saveState("第一個字符串");
originator.saveState("第二個字符串");
originator.saveState("第三個字符串");
originator.saveState("第四個字符串");
originator.saveState("第五個字符串");
// 讀取備忘錄中對象的狀態(tài)
Caretaker caretaker = new Caretaker(originator);
String state5 = caretaker.getState(4);
System.out.println(state5);
String state4 = caretaker.getState(3);
System.out.println(state4);
String state3 = caretaker.getState(2);
System.out.println(state3);
String state2 = caretaker.getState(1);
System.out.println(state2);
String state1 = caretaker.getState(0);
System.out.println(state1);
}
}運行以上代碼,得到以下輸出

五、總結
備忘錄模式給我們提供了一種可以恢復狀態(tài)的機制,可以使用戶能夠比較方便地回到某個歷史的狀態(tài),在此同時,備忘錄模式也實現(xiàn)了信息的封裝,使得用戶不需要關心狀態(tài)的保存細節(jié)。
但是,備忘錄模式的可擴展性并不是很好,每一種對象都需要對應一種備忘錄,這將會導致類的數(shù)量膨脹,對內存無疑是一種考驗。
到此這篇關于Java設計模式之備忘錄模式的文章就介紹到這了,更多相關Java備忘錄模式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Springboot實現(xiàn)發(fā)送郵件及注冊激活步驟
為了方便郵件發(fā)送功能的使用,我們用郵件發(fā)送功能實現(xiàn)用戶注冊,實現(xiàn)步驟大概就是進行用戶注冊同時發(fā)送一封激活郵件,郵件里附帶激活鏈接,關于Springboot發(fā)送郵件注冊激活功能的實現(xiàn)參考下本文吧2021-06-06
淺談Java異常的Exception e中的egetMessage()和toString()方法的區(qū)別
下面小編就為大家?guī)硪黄獪\談Java異常的Exception e中的egetMessage()和toString()方法的區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07
Java語言Consistent Hash算法學習筆記(代碼示例)
這篇文章主要介紹了Java語言Consistent Hash算法學習筆記(代碼示例),分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下2018-02-02

