Java設(shè)計模式之備忘錄模式使用詳解
前言
備忘錄模式(Memento Pattern): 保存對象的某個狀態(tài),以便在未來需要的時候進(jìn)行數(shù)據(jù)的恢復(fù)。相當(dāng)容易理解,舉個簡單的例子:Word 軟件在編輯時按 Ctrl+Z 組合鍵時能撤銷當(dāng)前操作,使文檔恢復(fù)到之前的狀態(tài);
一、備忘錄模式的基本介紹
【1】備忘錄模式(Memento Pattern): 在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)。這樣以后就可將該對象恢復(fù)到原先保存的狀態(tài)。
【2】現(xiàn)實生活中備忘錄是用來記錄某些要去做的事情,或者是記錄已經(jīng)達(dá)成共同意見的事情,以防忘記。而在軟件層面,備忘錄模式有著相同的含義,備忘錄對象主要用來記錄一個對象的某種狀態(tài),或者某些數(shù)據(jù),當(dāng)要做回退時,可以從備忘錄對象里獲取原來的數(shù)據(jù)進(jìn)行恢復(fù)操作。
【3】備忘錄模式屬于行為型模式。
【4】實現(xiàn)了信息的封裝,使得用戶不需要關(guān)心狀態(tài)和保存細(xì)節(jié)。符合 “單一職責(zé)原則” 。
【5】為了節(jié)約內(nèi)存,備忘錄模式可以和原型模式配合使用。
二、備忘錄模式的結(jié)構(gòu)與類圖
忘錄模式的核心是設(shè)計備忘錄類以及用于管理備忘錄的管理者類,備忘錄模式的主要角色如下:
【1】發(fā)起人(Originator)角色: 記錄當(dāng)前對象的內(nèi)部狀態(tài)信息,提供創(chuàng)建備忘錄和恢復(fù)備忘錄數(shù)據(jù)的功能,實現(xiàn)其他業(yè)務(wù)功能,它可以訪問備忘錄里的所有信息。
【2】備忘錄(Memetor)角色: 負(fù)責(zé)存儲發(fā)起人對象的內(nèi)部狀態(tài),在需要的時候提供這些內(nèi)部狀態(tài)給發(fā)起人。
【3】管理者(Caretaker)角色: 對備忘錄進(jìn)行管理,提供保存與獲取備忘錄的功能,但其不能對備忘錄的內(nèi)容進(jìn)行訪問與修改。
三、備忘錄模式案例分析
我們使用備忘錄模式寫一個學(xué)校 100 米考試的案例:5 人一組,進(jìn)行分組測試。我們需要備份的對象是,一組學(xué)生的成績。
【1】發(fā)起人(Originator)角色: 發(fā)起人需要依賴備忘錄類,對自己每次記錄的成績進(jìn)行備份 createMemento 。同時需要提供一個還原方法 getOriginalFromMemento 將需要的備份類作為參數(shù)傳遞進(jìn)來,并將結(jié)果賦值給目標(biāo)類。
//100 米 測試 5人一組 ,這是個人所花費的時間,我們使用備忘錄的方式實現(xiàn)一下。 public class Original { //姓名 private String name; //時間 private int timestamp; public Memento createMemento() { return new Memento(name, timestamp); } //獲取目標(biāo)對象 通過排名 public void getOriginalFromMemento(Memento memento) { name = memento.getName(); timestamp = memento.getTimestamp(); } public int getTimestamp() { return timestamp; } public void setTimestamp(int timestamp) { this.timestamp = timestamp; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Original [name=" + name + ", timestamp=" + timestamp + "]"; } }
【2】備忘錄(Memetor)角色: 提供一些目標(biāo)對象需要備份的屬性,通過構(gòu)造器進(jìn)行屬性傳遞。
public class Memento { //姓名 private String name; //時間 private int timestamp; //構(gòu)造器 public Memento(String name, int timestamp) { super(); this.name = name; this.timestamp = timestamp; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getTimestamp() { return timestamp; } public void setTimestamp(int timestamp) { this.timestamp = timestamp; } }
【3】管理者(Caretaker)角色: 創(chuàng)建一個存儲備忘錄對象的集合 <Map、List、Set>
等,同時創(chuàng)建添加、獲取、清空等方法。
public class Caretaker { //排名 private int index = 1; //用于順序存儲 參加測試的 十名同學(xué)的成績 Map<Integer, Memento> mementos = new HashMap<Integer, Memento>(); //提供一個 add 方法 public void add(Memento m) { mementos.put(index, m); index += 1; } //獲取備份類 public Memento get(int key) { return mementos.get(key); } //歸位 public void remove() { mementos.clear(); } }
【4】客戶端(Client)角色: 首先將順序按的前五名同學(xué)的成績及姓名,通過集合 Map 按照名次存儲。五名同學(xué)測試完成后,通過目標(biāo)類的 getOriginalFromMemento 方法,根據(jù)名次獲取同學(xué)的成績,并記錄在成績花名冊中。最后,清空記錄下一組。
public class Client { public static void main(String[] args) { //創(chuàng)建 目標(biāo)類 Original original = new Original(); //管理類 Caretaker managerMemento = new Caretaker(); //記錄成績 recordResults(original,managerMemento); //獲取第一名的成績 System.out.println("恢復(fù)前目標(biāo)類的記錄值"+original.toString()); //從集合中獲取第一名的值 Memento memento1 = managerMemento.get(1); //調(diào)用目標(biāo)類的還原方法 original.getOriginalFromMemento(memento1); System.out.println("恢復(fù)第一名的成績信息:"+original.toString()); //從集合中獲取第三名的值 Memento memento3 = managerMemento.get(3); //調(diào)用目標(biāo)類的還原方法 original.getOriginalFromMemento(memento3); System.out.println("恢復(fù)第三名的成績信息:"+original.toString()); //清空記錄下一組 managerMemento.remove(); } private static void recordResults(Original original,Caretaker managerMemento) { //第一名學(xué)生成績 original.setName("張三"); original.setTimestamp(2330); //創(chuàng)建一個備份類 Memento memento1 = original.createMemento(); //備份類存入 管理類中 managerMemento.add(memento1); //第二名學(xué)生成績 original.setName("李四"); original.setTimestamp(2550); //創(chuàng)建一個備份類 Memento memento2 = original.createMemento(); //備份類存入 管理類中 managerMemento.add(memento2); //第三名學(xué)生成績 original.setName("王五"); original.setTimestamp(2560); //創(chuàng)建一個備份類 Memento memento3 = original.createMemento(); //備份類存入 管理類中 managerMemento.add(memento3); } }
【5】結(jié)果展示: 備份者模式思想相對簡單,主要查看細(xì)節(jié)上的實現(xiàn)。備份類相對簡單,就一個普通類。但是目標(biāo)類,提供了存儲原始對象和獲取原始對象的方法,是備份者模式的精華所在。
恢復(fù)目標(biāo)類的記錄值Original [name=王五, timestamp=2560]
恢復(fù)第一名的成績信息:Original [name=張三, timestamp=2330]
恢復(fù)第三名的成績信息:Original [name=王五, timestamp=2560]
到此這篇關(guān)于Java設(shè)計模式之備忘錄模式使用詳解的文章就介紹到這了,更多相關(guān)Java備忘錄模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
剖析Spring WebFlux反應(yīng)式編程設(shè)計及工作原理
這篇文章主要為大家介紹了Spring WebFlux反應(yīng)式編程模型工作原理的剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-02-02springBoot解決static和@Component遇到的bug
這篇文章主要介紹了springBoot解決static和@Component遇到的bug,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02java進(jìn)制轉(zhuǎn)換工具類實現(xiàn)減少參數(shù)長度
這篇文章主要為大家介紹了java進(jìn)制轉(zhuǎn)換工具類實現(xiàn)減少參數(shù)長度示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02