深入淺出Java設(shè)計(jì)之備忘錄模式
發(fā)表時(shí)間:2024-01-17 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]一、引子 俗話說:世上難買后悔藥。所以凡事講究個(gè)“三思而后行”,但總常見有人做“痛心疾首”狀:當(dāng)初我要是……。如果真的有《大話西游》中能時(shí)光倒流的“月光寶盒”,那這世上也許會(huì)少一些傷感與后悔——當(dāng)然這只能是癡人說夢(mèng)了。 但是在我們手指下的程序世界里,卻有的后悔藥買。今天我們要講的備忘錄模式...
一、引子 俗話說:世上難買后悔藥。所以凡事講究個(gè)“三思而后行”,但總常見有人做“痛心疾首”狀:當(dāng)初我要是……。如果真的有《大話西游》中能時(shí)光倒流的“月光寶盒”,那這世上也許會(huì)少一些傷感與后悔——當(dāng)然這只能是癡人說夢(mèng)了。
但是在我們手指下的程序世界里,卻有的后悔藥買。今天我們要講的備忘錄模式便是程序世界里的“月光寶盒”。
二、定義與結(jié)構(gòu) 備忘錄(Memento)模式又稱標(biāo)記(Token)模式。GOF給備忘錄模式的定義為:在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài)。這樣以后就可將該對(duì)象恢復(fù)到原先保存的狀態(tài)。
在講命令模式的時(shí)候,我們?cè)?jīng)提到利用中間的命令角色可以實(shí)現(xiàn)undo、redo的功能。從定義可以看出備忘錄模式是專門來存放對(duì)象歷史狀態(tài)的,這對(duì)于很好的實(shí)現(xiàn)undo、redo功能有很大的幫助。所以在命令模式中undo、redo功能可以配合備忘錄模式來實(shí)現(xiàn)。
其實(shí)單就實(shí)現(xiàn)保存一個(gè)對(duì)象在某一時(shí)刻的狀態(tài)的功能,還是很簡(jiǎn)單的——將對(duì)象中要保存的屬性放到一個(gè)專門管理備份的對(duì)象中,需要的時(shí)候則調(diào)用約定好的方法將備份的屬性放回到原來的對(duì)象中去。但是你要好好看看為了能讓你的備份對(duì)象訪問到原對(duì)象中的屬性,是否意味著你就要全部公開或者包內(nèi)公開對(duì)象原本私有的屬性呢?如果你的做法已經(jīng)破壞了封裝,那么就要考慮重構(gòu)一下了。
備忘錄模式只是GOF對(duì)“恢復(fù)對(duì)象某時(shí)的原有狀態(tài)”這一問題提出的通用方案。因此在如何保持封裝性上——由于受到語言特性等因素的影響,備忘錄模式并沒有詳細(xì)描述,只是基于C++闡述了思路。那么基于Java的應(yīng)用應(yīng)該怎樣來保持封裝呢?我們將在實(shí)現(xiàn)一節(jié)里面討論。
來看下“月光寶盒”備忘錄模式的組成部分:
1) 備忘錄(Memento)角色:備忘錄角色存儲(chǔ)“備忘發(fā)起角色”的內(nèi)部狀態(tài)。“備忘發(fā)起角色”根據(jù)需要決定備忘錄角色存儲(chǔ)“備忘發(fā)起角色”的哪些內(nèi)部狀態(tài)。為了防止“備忘發(fā)起角色”以外的其他對(duì)象訪問備忘錄。備忘錄實(shí)際上有兩個(gè)接口,“備忘錄管理者角色”只能看到備忘錄提供的窄接口——對(duì)于備忘錄角色中存放的屬性是不可見的。“備忘發(fā)起角色”則能夠看到一個(gè)寬接口——能夠得到自己放入備忘錄角色中屬性。
2) 備忘發(fā)起(Originator)角色:“備忘發(fā)起角色”創(chuàng)建一個(gè)備忘錄,用以記錄當(dāng)前時(shí)刻它的內(nèi)部狀態(tài)。在需要時(shí)使用備忘錄恢復(fù)內(nèi)部狀態(tài)。
3) 備忘錄管理者(Caretaker)角色:負(fù)責(zé)保存好備忘錄。不能對(duì)備忘錄的內(nèi)容進(jìn)行操作或檢查。