Java設(shè)計模式之備忘錄模式
無論是我們在使用word還是記事本,系統(tǒng)都會為我們提供撤銷的功能,這幾乎是人人都會使用到的功能,而在我們實(shí)際開發(fā)中,會不會存在一個很復(fù)雜的對象,當(dāng)更改了其中的某一個屬性以后,也提供撤銷的功能,可以快速恢復(fù)到更新前的狀態(tài)。提供該功能的模式也正是今天的主題——備忘錄模式。
一、概念理解
書上備忘錄的解釋是,在不破壞封裝的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài),這樣可以在以后將對象恢復(fù)到原先保存的狀態(tài)。
其實(shí)也就是在一個對象之外再額外的增加一個副本對象,每當(dāng)我們在對象上更改一些屬性以后就構(gòu)建一個副本,并把副本存放在一個隊列中,每當(dāng)回退該對象的時候就從副本中恢復(fù)數(shù)據(jù)。
很顯然需要三個角色:原對象、副本對象、存放副本的隊列。
也即書上的三個角色定義:
Originator(發(fā)起人角色):負(fù)責(zé)創(chuàng)建一個備忘錄,記錄自身需要保存的狀態(tài),具備狀態(tài)回滾功能;即原對象。
Memento(備忘錄角色):用于存儲Originator的內(nèi)部狀態(tài),且可以防止Originator以外的對象進(jìn)行訪問;即副本對象。
Caretaker(管理員角色):負(fù)責(zé)存儲、提供管理Memento,無法對Memento的內(nèi)容進(jìn)行操作和訪問;也即存放副本的隊列。
為了讓概念落地,我們基于備忘錄模式的思想實(shí)現(xiàn)視頻草稿箱的功能。
在這個業(yè)務(wù)場景中,發(fā)起人其實(shí)就是編輯視頻的編輯器,在這個編輯器中我們能干啥呢?編輯視頻、從草稿箱導(dǎo)入、保存到草稿箱。這不是就是發(fā)起人角色的作用嗎!我們稱為編輯草稿。
備忘錄那不就是草稿修改后嗎,我們稱之為完稿。
完稿做好了,要存放到一個列表中用于我們快速修復(fù),那當(dāng)然就是管理員角色。
基于三個角色我們實(shí)現(xiàn)代碼。
二、案例實(shí)現(xiàn)
備忘錄角色(完稿):
就是個基礎(chǔ)對象,用于存儲數(shù)據(jù),視頻包含的屬性主要是,標(biāo)題、封面、視頻地址
/** * 備忘錄(完稿) * @author tcy * @Date 16-09-2022 */ public class VideoMemento { private String title; private String videoUrl; private String imgs; public VideoMemento(String title, String content, String imgs) { this.title = title; this.videoUrl = content; this.imgs = imgs; } public String getTitle() { return title; } public String getContent() { return videoUrl; } public String getImgs() { return imgs; } @Override public String toString() { return "ArticleMemento{" + "title='" + title + '\'' + ", content='" + videoUrl + '\'' + ", imgs='" + imgs + '\'' + '}'; } }
發(fā)起人角色(編輯草稿):
在基本對象之上,增加保存和撤銷的操作,可以看到和我們定義的完稿長的一樣,只是又增了saveToMemento()方法和undoFromMemento()方法,用于保存和撤銷。
/** * 發(fā)起人 (草稿) * @author tcy * @Date 16-09-2022 */ public class Editor { private String title; private String videoUrl; private String imgs; public Editor(String title, String videoUrl, String imgs) { this.title = title; this.videoUrl = videoUrl; this.imgs = imgs; } public String getTitle() { return title; } public String getContent() { return videoUrl; } public String getImgs() { return imgs; } public void setTitle(String title) { this.title = title; } public void setContent(String content) { this.videoUrl = content; } public void setImgs(String imgs) { this.imgs = imgs; } /** * 保存到備忘錄 * @return */ public VideoMemento saveToMemento(){ VideoMemento articleMemento = new VideoMemento(this.title,this.videoUrl,this.imgs); return articleMemento; } /** * 從備忘錄恢復(fù) * @param articleMemento */ public void undoFromMemento(VideoMemento articleMemento){ this.title = articleMemento.getTitle(); this.videoUrl = articleMemento.getContent(); this.imgs = articleMemento.getImgs(); } @Override public String toString() { return "Editor{" + "title='" + title + '\'' + ", content='" + videoUrl + '\'' + ", imgs='" + imgs + '\'' + '}'; } }
管理員角色(草稿箱):
包括一個棧,用于存儲完稿,利用棧先進(jìn)后出的特性,實(shí)現(xiàn)逐步的撤銷。
/** * 管理者(草稿箱) * @author tcy * @Date 16-09-2022 */ public class Caretaker { private final Stack<VideoMemento> STACK = new Stack<VideoMemento>(); public VideoMemento getMemento(){ VideoMemento videoMemento = STACK.pop(); return videoMemento; } public void addMemento(VideoMemento videoMemento){ STACK.push(videoMemento); } }
讀者可以拉取完整代碼到本地進(jìn)行學(xué)習(xí),實(shí)現(xiàn)代碼均測試通過后上傳到碼云,本地下載。
三、總結(jié)
備忘錄模式是怎么回事想必你已經(jīng)明白了,如果我們在實(shí)際開發(fā)中有一個對象的功能很復(fù)雜,屬性非常的多,這時候備忘錄模式就是一個好的選擇。
備忘錄模式實(shí)現(xiàn)也很簡單,在原對象基礎(chǔ)之上再增加一個副本對象,在原對象上額外的增加兩個方法,用于構(gòu)建一個副本和從副本中取值。再創(chuàng)建一個棧對象,用于存儲、管理副本。
備忘錄模式的優(yōu)勢突出,會簡化發(fā)起人(原對象)的職責(zé),隔離存儲狀態(tài),實(shí)現(xiàn)信息的封裝,客戶端無須關(guān)心保存細(xì)節(jié),而且提供了狀態(tài)回滾功能。
但是最顯著的缺點(diǎn)就是消耗資源,如果對象改動較大,每一次保存都會消耗很大的內(nèi)存空間,功能換空間。
備忘錄模式在Jdk和Spring中應(yīng)用的并不多,在我們實(shí)際應(yīng)用中我們要衡量空間和效率的影響,是否使用備忘錄模式進(jìn)行合理的取舍。
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
相關(guān)文章
Spring?Boot?+?Spring?Batch?實(shí)現(xiàn)批處理任務(wù)的詳細(xì)教程
這篇文章主要介紹了Spring?Boot+Spring?Batch實(shí)現(xiàn)批處理任務(wù),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-08-08Mybatis如何通過出入Map參數(shù)作為條件進(jìn)行查詢
這篇文章主要介紹了Mybatis如何通過出入Map參數(shù)作為條件進(jìn)行查詢,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06Eclipse中查看android工程代碼出現(xiàn)"android.jar has no source attachment
這篇文章主要介紹了Eclipse中查看android工程代碼出現(xiàn)"android.jar has no source attachment"的解決方案,需要的朋友可以參考下2016-05-05Mybatis開發(fā)環(huán)境搭建實(shí)現(xiàn)數(shù)據(jù)的增刪改查功能
這篇文章主要介紹了 Mybatis開發(fā)環(huán)境搭建實(shí)現(xiàn)數(shù)據(jù)的增刪改查功能,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-03-03