設計模式讀書筆記-----備忘錄模式

? ? ? ?個人比較喜歡玩單機游戲,什么仙劍、古劍、鬼泣、使命召喚、三國無雙等等一系列的游戲我都玩過(現在期待凡人修仙傳),對于這些游戲除了劇情好、場面大、爽快之外,還可以隨時存檔,等到下次想玩了又可以從剛開始的位置玩起(貌似現在的游戲都有)。這里的所謂存檔就是將當前的狀態記錄下來,打開存檔的時候只需要將這些狀態讀取出來即可。還有我們小時候期待長大,長大了希望回到小時候。18歲想長到28歲,到了28想還是18好!!!


? ? ? ?上面所提到的就是“后悔藥”機制。在我們生活中,做錯事了我們都期望可以從新開始,希望這個世界上有后悔藥可以吃,但現實是殘酷的,這個世界是沒有后悔藥可以吃!雖然在現實社會中不可以實現,我們可以在軟件的世界里實現(現在好多軟件有撤銷功能:Ctrl+Z不就是么)。

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


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

? ? ? ?一、 模式定義

? ? ? ?所謂備忘錄模式就是在不破壞封裝的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態,這樣可以在以后將對象恢復到原先保存的狀態。

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


? ? ? ?二、 模式結構

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


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

? ? ? ? ??Originator:?原發器。負責創建一個備忘錄,用以記錄當前對象的內部狀態,通過也可以使用它來利用備忘錄恢復內部狀態。同時原發器還可以根據需要決定Memento存儲Originator的那些內部狀態。

? ? ? ? ??Memento:?備忘錄。用于存儲Originator的內部狀態,并且可以防止Originator以外的對象訪問Memento。在備忘錄Memento中有兩個接口,其中Caretaker只能看到備忘錄中的窄接口,它只能將備忘錄傳遞給其他對象。Originator可以看到寬接口,允許它訪問返回到先前狀態的所有數據。

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

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

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

? ? ? ? ??對原發器:可以訪問備忘錄里的所有信息。

? ? ? ? ??對負責人:不可以訪問備忘錄里面的數據,但是他可以保存備忘錄并且可以將備忘錄傳遞給其他對象。

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

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

? ? ? ?典型的備忘錄代碼如下:

class Memento {private String state;public Memento(Originator o){state = o.state;}public void setState(String state){this.state=state;}public String getState(){return this.state;}  
}

? ? ? ?

? ? ? ? ?三、 模式實現

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


? ? ? ?首先是游戲角色類:Role.java

private int bloodFlow;private int magicPoint;public Role(int bloodFlow,int magicPoint){this.bloodFlow = bloodFlow;this.magicPoint = magicPoint;}public int getBloodFlow() {return bloodFlow;}public void setBloodFlow(int bloodFlow) {this.bloodFlow = bloodFlow;}public int getMagicPoint() {return magicPoint;}public void setMagicPoint(int magicPoint) {this.magicPoint = magicPoint;}/*** @desc 展示角色當前狀態* @return void*/public void display(){System.out.println("用戶當前狀態:");System.out.println("血量:" + getBloodFlow() + ";藍量:" + getMagicPoint());}/*** @desc 保持存檔、當前狀態* @return* @return Memento*/public Memento saveMemento(){return new Memento(getBloodFlow(), getMagicPoint());}/*** @desc 恢復存檔* @param memento* @return void*/public void restoreMemento(Memento memento){this.bloodFlow = memento.getBloodFlow();this.magicPoint = memento.getMagicPoint();}
}

? ? ? ?備忘錄:Memento.java

class Memento {private int bloodFlow;private int magicPoint;public int getBloodFlow() {return bloodFlow;}public void setBloodFlow(int bloodFlow) {this.bloodFlow = bloodFlow;}public int getMagicPoint() {return magicPoint;}public void setMagicPoint(int magicPoint) {this.magicPoint = magicPoint;}public Memento(int bloodFlow,int magicPoint){this.bloodFlow = bloodFlow;this.magicPoint = magicPoint;}
}

? ? ? ?負責人:Caretaker.java

public class Caretaker {Memento memento;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}}

? ? ? ??客戶端:Client.java

public class Client {public static void main(String[] args) {//打BOSS之前:血、藍全部滿值Role role = new Role(100, 100);System.out.println("----------大戰BOSS之前----------");role.display();//保持進度Caretaker caretaker = new Caretaker();caretaker.memento = role.saveMemento();//大戰BOSS,快come Over了role.setBloodFlow(20);role.setMagicPoint(20);System.out.println("----------大戰BOSS----------");role.display();//恢復存檔role.restoreMemento(caretaker.getMemento());System.out.println("----------恢復----------");role.display();}
}

? ? ? ?運行結果



? ? ? ?四、 模式的優缺點

? ? ? ?優點

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

? ? ? ? ??2、 實現了信息的封裝。使得用戶不需要關心狀態的保存細節。

? ? ? ?缺點

? ? ? ? ??消耗資源。如果類的成員變量過多,勢必會占用比較大的資源,而且每一次保存都會消耗一定的內存。


? ? ? ?五、 模式適用場景

? ? ? ? ?1、 需要保存一個對象在某一個時刻的狀態或部分狀態。

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


? ? ? ?六、 模式總結

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

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

? ? ? ?3、 備忘錄模式會占用較多的內存,消耗資源。

轉載于:https://www.cnblogs.com/oversea201405/p/3752109.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/377790.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/377790.shtml
英文地址,請注明出處:http://en.pswp.cn/news/377790.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C++grammar】vector類和字符串字面量

C的vector類 用數組存放數據時&#xff0c;容量大小不可變&#xff0c;vector對象容量可自動增大。 vector的操作&#xff1a; 調用push_back函數時&#xff0c;vector對象的容量可能會增大。 觀察下列操作對vector的影響&#xff1a; #include <vector> #include <…

除去數組中的空字符元素array_filter

<?php$str1_arrayarray(電影,,http://www,,1654,);$str1_arrayarray_filter($str1_array);print_r($str1_array); ?>顯示結果&#xff1a;Array( [0] > 電影 [2] > http://www [4] > 1654) 轉載于:https://www.cnblogs.com/skillCoding/archive/20…

date.after方法_Java Date after()方法與示例

date.after方法日期類after()方法 (Date Class after() method) after() method is available in java.util package. after()方法在java.util包中可用。 after() method is used to check whether this date is after the given date (d) or not. after()方法用于檢查此日期是…

Matplotlib(數據可視化庫)---講解

本內容來自《跟著迪哥學Python數據分析與機器學習實戰》&#xff0c;該篇博客將其內容進行了整理&#xff0c;加上了自己的理解&#xff0c;所做小筆記。若有侵權&#xff0c;聯系立刪。 迪哥說以下的許多函數方法都不用死記硬背&#xff0c;多查API多看文檔&#xff0c;確實&a…

找min和max

看到的貌似是阿里的筆試題&#xff0c;題意是一組數&#xff0c;要找到min和max&#xff0c;同時要求時間復雜度&#xff08;比較次數&#xff09;小于2n&#xff08;2n的辦法都想得到&#xff09;。 別人的思路&#xff1a;n個數的數組里看作每兩個一組&#xff0c;若n是奇數&…

Shader Compiler 界面進展1

先從模仿Composer的界面開始. 目前的進展:不用不知道,雖然wxweidgets有很多界面工具如DialogBlocks(DB), 但仍然不好使. 我使用wxAui界面, DialogBlocks并不支持輸出其xrc格式, 我猜是wx本身就沒有解析wxAui的xrc格式.像wxAuiToolBar或其他wxToolBar, DB工具也不能獨立輸出xrc.…

leetcode 90. 子集 II 思考分析

與本題相關聯的題目解析&#xff1a; leetcode 78. 子集 思考分析 leetcode 40. 組合總和 II思考分析 題目 給定一個可能包含重復元素的整數數組 nums&#xff0c;返回該數組所有可能的子集&#xff08;冪集&#xff09;。 說明&#xff1a;解集不能包含重復的子集。 思考 …

java bitset_Java BitSet and()方法與示例

java bitsetBitSet類和()方法 (BitSet Class and() method) and() method is available in java.util package. and()方法在java.util包中可用。 and() method is used to perform logical AND between two Bitset. This bit set is updated so that every bit holds the value…

Redis-主從復制

一、Redis的Replication&#xff1a; 這里首先需要說明的是&#xff0c;在Redis中配置Master-Slave模式真是太簡單了。相信在閱讀完這篇Blog之后你也可以輕松做到。這里我們還是先列出一些理論性的知識&#xff0c;后面給出實際操作的案例。 下面的列表清楚的解釋了Redis…

.wav音樂文件轉換為.fft.npy頻譜格式文件

需要修改的地方 十個文件夾&#xff0c;每個文件夾下都有100首.au格式的音樂&#xff0c;這里舉個例子&#xff0c;那其中5個類別進行轉換 genre_list ["classical", "jazz", "country", "pop", "rock", "metal"…

WINDOWS編程筆記 2012.2.7

操作系統感知事件和傳遞事件是通過消息機制來實現的typedef struct tagMSG{ HWND hwnd; //窗口的句柄 UINT message; WPARAM wParam; //信息的附加參數 LPARAM lParam; DWORD time; //消息傳遞的時間 POINT pt; //消息投遞的時候&#xff0c;光標的位置}…

php 郵件驗證_PHP程序來驗證電子郵件地址

php 郵件驗證Suppose there is a form floating where every user has to fill his/her email ID. It might happen that due to typing error or any other problem user doesnt fill his/her mail ID correctly. Then at that point, the program should be such that it sho…

【C++grammar】結構化綁定

目錄定義1、用于原生數組的結構化綁定聲明2、用于std::array的結構化綁定聲明3、用于對象數據成員的結構化綁定聲明定義 結構化綁定聲明是一個聲明語句&#xff0c;意味著聲明了一些標識符并對標識符做了初始化。將指定的一些名字綁定到初始化器的子對象或者元素上。 對于初始…

URAL 1106 Two Teams (DFS)

題意 小組里有N個人&#xff0c;每個人都有一個或多個朋友在小組里。將小組分成兩個隊伍&#xff0c;每個隊伍的任意一個成員都有至少一個朋友在另一個隊伍。 思路 一開始覺得和前幾天做過的一道2-sat&#xff08;每個隊伍任意兩個成員都必須互相認識&#xff09;相似然后就往那…

七、邏輯回歸項目實戰---音樂分類器

一、項目需求 訓練集數據為六類音樂([“classical”, “jazz”, “country”, “pop”, “rock”, “metal”])&#xff0c;格式為.wav&#xff0c;每類音樂都有100首 音樂分類器項目&#xff0c;主要運用到了傅里葉變換函數 很多東西越在高維空間處理起來就會變得越是簡單 例…

仿京東左側欄目導航

效果圖&#xff1a; 查看效果&#xff1a;http://www.miiceic.org.cn/eg/eg10/abzc.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http:…

python創建矩陣_在Python中創建矩陣的Python程序

python創建矩陣There is no specific data type in Python to create a matrix, we can use list of list to create a matrix. Python中沒有特定的數據類型來創建矩陣&#xff0c;我們可以使用list列表來創建矩陣 。 Consider the below example, 考慮下面的示例&#xff0c;…

函數定義

//表達式定義函數 var squarefunction(x){return x*x;}//只有變量聲明(var square;)提前了&#xff0c;初始化代碼仍然在原處。 //函數聲明語句 function f(x){return x*x;}//整個函數體被顯式的“提前”到了腳本或函數的頂部。 //因此他們在整個腳本和函數內都是可見的。此種方…

leetcode 491. 遞增子序列 思考分析

題目 給定一個整型數組, 你的任務是找到所有該數組的遞增子序列&#xff0c;遞增子序列的長度至少是2。 說明: 給定數組的長度不會超過15。 數組中的整數范圍是 [-100,100]。 給定數組中可能包含重復數字&#xff0c;相等的數字應該被視為遞增的一種情況。 思考 這一題和le…

八、神經網絡

一、為啥要有神經網絡&#xff1f; 在前面的幾篇博客中&#xff0c;很容易知道我們處理的都是線性的數據&#xff0c;例如&#xff1a;線性回歸和邏輯回歸&#xff0c;都是線性的算法 但是&#xff0c;實際上日常生活中所遇到的數據或者問題絕大多數還是非線性的 一般面對非線…