無論是我們在使用word還是記事本,系統都會為我們提供撤銷的功能,這幾乎是人人都會使用到的功能,而在我們實際開發中,會不會存在一個很復雜的物件,當更改了其中的某一個屬性以后,也提供撤銷的功能,可以快速恢復到更新前的狀態,提供該功能的模式也正是今天的主題——備忘錄模式,
一、概念理解
書上備忘錄的解釋是,在不破壞封裝的前提下,捕獲一個物件的內部狀態,并在該物件之外保存這個狀態,這樣可以在以后將物件恢復到原先保存的狀態,
其實也就是在一個物件之外再額外的增加一個副本物件,每當我們在物件上更改一些屬性以后就構建一個副本,并把副本存放在一個佇列中,每當回退該物件的時候就從副本中恢復資料,
很顯然需要三個角色:原物件、副本物件、存放副本的佇列,
也即書上的三個角色定義:
Originator(發起人角色):負責創建一個備忘錄,記錄自身需要保存的狀態,具備狀態回滾功能;即原物件,
Memento(備忘錄角色):用于存盤Originator的內部狀態,且可以防止Originator以外的物件進行訪問;即副本物件,
Caretaker(管理員角色):負責存盤、提供管理Memento,無法對Memento的內容進行操作和訪問;也即存放副本的佇列,
為了讓概念落地,我們基于備忘錄模式的思想實作視頻草稿箱的功能,
在這個業務場景中,發起人其實就是編輯視頻的編輯器,在這個編輯器中我們能干啥呢?編輯視頻、從草稿箱匯入、保存到草稿箱,這不是就是發起人角色的作用嗎!我們稱為編輯草稿,
備忘錄那不就是草稿修改后嗎,我們稱之為完稿,
完稿做好了,要存放到一個串列中用于我們快速修復,那當然就是管理員角色,
基于三個角色我們實作代碼,
二、案例實作
備忘錄角色(完稿):
就是個基礎物件,用于存盤資料,視頻包含的屬性主要是,標題、封面、視頻地址
/**
* 備忘錄(完稿)
* @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 + '\'' +
'}';
}
}
發起人角色(編輯草稿):
在基本物件之上,增加保存和撤銷的操作,可以看到和我們定義的完稿長的一樣,只是又增了saveToMemento()方法和undoFromMemento()方法,用于保存和撤銷,
/**
* 發起人 (草稿)
* @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;
}
/**
* 從備忘錄恢復
* @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 + '\'' +
'}';
}
}
管理員角色(草稿箱):
包括一個堆疊,用于存盤完稿,利用堆疊先進后出的特性,實作逐步的撤銷,
/**
* 管理者(草稿箱)
* @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);
}
}
讀者可以拉取完整代碼到本地進行學習,實作代碼均測驗通過后上傳到碼云,
三、總結
備忘錄模式是怎么回事想必你已經明白了,如果我們在實際開發中有一個物件的功能很復雜,屬性非常的多,這時候備忘錄模式就是一個好的選擇,
備忘錄模式實作也很簡單,在原物件基礎之上再增加一個副本物件,在原物件上額外的增加兩個方法,用于構建一個副本和從副本中取值,再創建一個堆疊物件,用于存盤、管理副本,
備忘錄模式的優勢突出,會簡化發起人(原物件)的職責,隔離存盤狀態,實作資訊的封裝,客戶端無須關心保存細節,而且提供了狀態回滾功能,
但是最顯著的缺點就是消耗資源,如果物件改動較大,每一次保存都會消耗很大的記憶體空間,功能換空間,
備忘錄模式在Jdk和Spring中應用的并不多,在我們實際應用中我們要衡量空間和效率的影響,是否使用備忘錄模式進行合理的取舍,
一、設計模式概述
二、設計模式之工廠方法和抽象工廠
三、設計模式之單例和原型
四、設計模式之建造者模式
五、設計模式之代理模式
六、設計模式之配接器模式
七、設計模式之橋接模式
八、設計模式之組合模式
九、設計模式之裝飾器模式
十、設計模式之外觀模式
十一、外觀模式之享元模式
十二、設計模式之責任鏈模式
十三、設計模式之命令模式
十四、設計模式之解釋器模式
十五、設計模式之迭代器模式
十六、設計模式之中介者模式
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/509063.html
標籤:其他
上一篇:我的設計模式之旅、12 原型模式
下一篇:新消費時代,零售業的進與退?
