日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Go設(shè)計(jì)模式--備忘錄模式,帶暫存的業(yè)務(wù)功能可以參考它來實(shí)現(xiàn)

大家好,這里是每周都在陪你一起進(jìn)步的網(wǎng)管~!今天繼續(xù)學(xué)習(xí)設(shè)計(jì)模式—備忘錄模式

創(chuàng)新互聯(lián)云計(jì)算的互聯(lián)網(wǎng)服務(wù)提供商,擁有超過13年的服務(wù)器租用、電信內(nèi)江機(jī)房、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗(yàn),已先后獲得國(guó)家工業(yè)和信息化部頒發(fā)的互聯(lián)網(wǎng)數(shù)據(jù)中心業(yè)務(wù)許可證。專業(yè)提供云主機(jī)、虛擬主機(jī)、域名申請(qǐng)、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。

備忘錄模式(Memento Pattern)又叫作快照模式(Snapshot Pattern), 或令牌模式(Token Pattern), 指在不破壞封裝的前提下, 捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài), 并在對(duì)象之外保存這個(gè)狀態(tài)。 這樣以后就可將該對(duì)象恢復(fù)到原先保存的狀態(tài), 屬于行為型設(shè)計(jì)模式。

備忘錄模式主要適用于以下應(yīng)用場(chǎng)景。

  1. 需要保存歷史快照的場(chǎng)景。
  2. 希望在對(duì)象之外保存狀態(tài),且除了自己,其他類對(duì)象無法訪問狀態(tài)保存的具體內(nèi)容。

備忘錄模式是一種行為型設(shè)計(jì)模式。這種模式允許我們保存對(duì)象在某些關(guān)鍵節(jié)點(diǎn)時(shí)的必要信息,以便于在適當(dāng)?shù)臅r(shí)候可以將之恢復(fù)到之前的狀態(tài)。通常它可以用來幫助設(shè)計(jì)撤銷/恢復(fù)操作。

備忘錄模式的類結(jié)構(gòu)

下面是備忘錄模式的類圖,

圖片來自https://refactoringguru.cn/design-patterns/memento,我后面實(shí)現(xiàn)的時(shí)候不會(huì)完全按照這個(gè)結(jié)構(gòu)去實(shí)現(xiàn),這里先把結(jié)構(gòu)里的各個(gè)角色給大家說清楚。

備忘錄模式中主要有這三個(gè)角色的類

  • Originator(發(fā)起者):Originator是當(dāng)前的基礎(chǔ)對(duì)象,它會(huì)將自己的狀態(tài)保存進(jìn)備忘錄,此角色可以類比博客系統(tǒng)中的文章對(duì)象
  • 發(fā)起者中要有保存方法和從備忘錄中恢復(fù)狀態(tài)的方法,保存方法會(huì)返回當(dāng)時(shí)狀態(tài)組成的備忘錄對(duì)象
  • Memento(備忘錄) : 存儲(chǔ)著Originator的狀態(tài)的對(duì)象,類比理解即為文章對(duì)象的不同版本。
  • Caretaker(管理人):Caretaker是保存著多條備忘錄的對(duì)象,并維護(hù)著備忘錄的索引,在需要的時(shí)候會(huì)返回相應(yīng)的備忘錄 -- 類比理解為博客系統(tǒng)中的編輯器對(duì)象
  • 管理者的保存和恢復(fù)操作,會(huì)代理其持有的發(fā)起者對(duì)象的保存和恢復(fù)操作,在這些代理方法中會(huì)增加對(duì)備忘錄對(duì)象列表、當(dāng)前備忘錄版本的維護(hù)。

上面這個(gè)類圖結(jié)構(gòu)是實(shí)現(xiàn)備忘錄模式的最簡(jiǎn)單方式,真實(shí)使用的時(shí)候,Caretaker,Originator、memento 這些角色可以繼續(xù)抽象出對(duì)應(yīng)的接口和實(shí)現(xiàn)。這里就不搞那么復(fù)雜了,要舉的例子比較簡(jiǎn)單,這么一拆顯得這個(gè)模式用起來特別費(fèi)事兒。

其實(shí)其他設(shè)計(jì)模式也是一樣,學(xué)習(xí)的時(shí)候大家知道了它的結(jié)構(gòu)后,在實(shí)現(xiàn)應(yīng)用的環(huán)節(jié)不必完完全全按照結(jié)構(gòu)一板一眼地全部進(jìn)行實(shí)現(xiàn),有的應(yīng)用場(chǎng)景并不復(fù)雜,能合并的角色可以按需進(jìn)行合并。

應(yīng)用舉例

場(chǎng)景

某線上博客平臺(tái), 需為用戶提供在線編輯文章功能,文章主要包括標(biāo)題 - title 和內(nèi)容 - content等信息。為最大程度防止異常情況導(dǎo)致編輯內(nèi)容的丟失, 需要提供版本暫存和Undo, Redo功能。

"版本暫存"問題可以應(yīng)用備忘錄模式, 將編輯器的狀態(tài)完整保存起來(主要就是編輯內(nèi)容),Undo和Redo的本質(zhì), 是在歷史版本中前后移動(dòng)把當(dāng)時(shí)保存的內(nèi)容加載到文章對(duì)象上。

方案設(shè)計(jì)

  • IEditor: 定義編輯器接口
  • EditorMemento: 定義編輯器的備忘錄, 也就是編輯器的內(nèi)部狀態(tài)數(shù)據(jù)模型, 同時(shí)也對(duì)應(yīng)一個(gè)歷史版本
  • Editor: 編輯器類, 實(shí)現(xiàn)IEditor接口

這個(gè)例子里我們把原發(fā)器和管理人兩個(gè)角色集中在Editor類型上一起實(shí)現(xiàn),例子比較簡(jiǎn)單,就沒有單獨(dú)實(shí)現(xiàn)一個(gè)Article類型作為原發(fā)器角色,如果你想完全按照備忘錄模式的結(jié)構(gòu)實(shí)現(xiàn),把Title、Content這寫屬性和Save方法抽離到單獨(dú)的Article類型上,再讓Editor嵌套組合Article即可。

下面我們根據(jù)UML類圖實(shí)現(xiàn)一下這個(gè)帶Undo、Redo功能的編輯器。

代碼實(shí)現(xiàn)

首先在IEditor 接口里定義編輯器對(duì)象要實(shí)現(xiàn)的行為

// 編輯器接口定義
type IEditor interface {
Title(title string)
Content(content string)
Save()
Undo() error
Redo() error
Show()
}

接下來定義編輯器的備忘錄, 也就是編輯器的內(nèi)部狀態(tài)數(shù)據(jù)模型, 同時(shí)也對(duì)應(yīng)一個(gè)歷史版本。

"本文使用的完整可運(yùn)行源碼
去公眾號(hào)「網(wǎng)管叨bi叨」發(fā)送【設(shè)計(jì)模式】即可領(lǐng)取"
type Memento struct {
title string
content string
createTime int64
}

func newMemento(title string, content string) *Memento {
return &Memento{
title, content, time.Now().Unix(),
}
}

然后是最復(fù)雜的Editor實(shí)現(xiàn),它會(huì)實(shí)現(xiàn)上面IEditor接口中定義的所有行為,其中的Undo、Redo方法即回退、前進(jìn)方法在實(shí)現(xiàn)的時(shí)候就是依賴的它內(nèi)部記錄的一組Memento對(duì)象,通過指向不同的Memento對(duì)象來實(shí)現(xiàn)回退和前進(jìn)功能。

"本文使用的完整可運(yùn)行源碼
去公眾號(hào)「網(wǎng)管叨bi叨」發(fā)送【設(shè)計(jì)模式】即可領(lǐng)取"
// 編輯器類, 實(shí)現(xiàn)IEditor接口
type Editor struct {
title string
content string
versions []*Memento
index int
}

func NewEditor() IEditor {
return &Editor{
"", "", make([]*Memento, 0), 0,
}
}

func (editor *Editor) Title(title string) {
editor.title = title
}

func (editor *Editor) Content(content string) {
editor.content = content
}

func (editor *Editor) Save() {
it := newMemento(editor.title, editor.content)
editor.versions = append(editor.versions, it)
editor.index = len(editor.versions) - 1
}

func (editor *Editor) Undo() error {
return editor.load(editor.index - 1)
}

func (editor *Editor) load(i int) error {
size := len(editor.versions)
if size <= 0 {
return errors.New("no history versions")
}

if i < 0 || i >= size {
return errors.New("no more history versions")
}

it := editor.versions[i]
editor.title = it.title
editor.content = it.content
editor.index = i
return nil
}

func (editor *Editor) Redo() error {
return editor.load(editor.index + 1)
}

func (editor *Editor) Show() {
fmt.Printf("MockEditor.Show, title=%s, cnotallow=%s\n", editor.title, editor.content)
}

最后我們來測(cè)試一下Editor的版本記錄功能

"本文使用的完整可運(yùn)行源碼
去公眾號(hào)「網(wǎng)管叨bi叨」發(fā)送【設(shè)計(jì)模式】即可領(lǐng)取"
func main() {
editor := NewEditor()

// test save()
editor.Title("唐詩(shī)")
editor.Content("白日依山盡")
editor.Save()

editor.Title("唐詩(shī) 登鸛雀樓")
editor.Content("白日依山盡, 黃河入海流. ")
editor.Save()

editor.Title("唐詩(shī) 登鸛雀樓 王之渙")
editor.Content("白日依山盡, 黃河入海流。欲窮千里目, 更上一層樓。")
editor.Save()

// test show()
fmt.Println("-------------Editor 當(dāng)前內(nèi)容-----------")
editor.Show()

fmt.Println("-------------Editor 回退內(nèi)容-----------")
for {
e := editor.Undo()
if e != nil {
break
} else {
editor.Show()
}
}

fmt.Println("-------------Editor 前進(jìn)內(nèi)容-----------")
for {
e := editor.Redo()
if e != nil {
break
} else {
editor.Show()
}
}
}

運(yùn)行程序后會(huì)有類似下面的顯示


分享標(biāo)題:Go設(shè)計(jì)模式--備忘錄模式,帶暫存的業(yè)務(wù)功能可以參考它來實(shí)現(xiàn)
文章鏈接:http://www.5511xx.com/article/djeiooo.html