小A:“那‘月光寶盒’備忘錄模式有哪些組成部分?”
大B:“1、備忘錄(Memento)角色:備忘錄角色存儲‘備忘發起角色’的內部狀態。‘備忘發起角色’根據需要決定備忘錄角色存儲‘備忘發起角色’的哪些內部狀態。為了防止‘備忘發起角色’以外的其他對象訪問備忘錄。 備忘錄實際上有兩個接口,‘備忘錄管理者角色’隻能看到備忘錄提供的窄接口——對於備忘錄角色中存放的屬性是不可見的。‘備忘發起角色’則能夠看到一個寬接口——能夠得到自己放入備忘錄角色中屬性。2、備忘發起(Originator)角色:‘備忘發起角色’創建一個備忘錄,用以記錄當前時刻它的內部狀態。在需要時使用備忘錄恢複內部狀態。3、備忘錄管理者(Caretaker)角色:負責保存好備忘錄。不能對備忘錄的內容進行操作或檢查。稱它為寬接口;而另一個則可以隻是一個標示,稱它為窄接口。 備忘錄角色要實現這兩個接口類。這樣對於‘備忘發起角色’采用寬接口進行訪問,而對於其他的角色或者對象則采用窄接口進行訪問。這種實現比較簡單,但是需要人為的進行規範約束——而這往往是沒有力度的。第二種方法便很好的解決了第一種的缺陷:采用內部類來控製訪問權限。將備忘錄角色作為‘備忘發起角色’的一個私有內部類。好處就不詳細解釋了,看看代碼就明白了。下麵的代碼是一個完整的備忘錄模式的程序。它便采用了第二種方法來實現備忘錄模式。還有一點值得指出的是,在下麵的代碼中,對於客戶程序來說‘備忘錄管理者角色’是不可見的,這樣簡化了客戶程序使用備忘錄模式的難度。下麵采用‘備忘發起角色’來調用訪問‘備忘錄管理者角色’,也可以參考外觀模式在客戶程序與備忘錄角色之間添加一個外觀角色。”
//這個是要保存的狀態
//保持一個“備忘錄管理者角色”的對象
//讀取備忘錄角色以恢複以前的狀態
//創建一個備忘錄角色,並將當前狀態屬性存入,托給“備忘錄管理者角色”存放。
//作為私有內部類的備忘錄角色,它實現了窄接口,可以看到在第二種方法中寬接口已經不再需要
//注意:裏麵的屬性和方法都是私有的
//測試代碼——客戶程序
//窄接口
//“備忘錄管理者角色”
大B:“第三種方式是不太推薦使用的:使用clone方法來簡化備忘錄模式。由於Java提供了clone機製,這使得複製一個對象變得輕鬆起來。使用了clone機製的備忘錄模式,備忘錄角色基本可以省略了,而且可以很好的保持對象的封裝。但是在為你的類實現clone方法時要慎重!在上麵的代碼中,簡單的模擬了備忘錄模式的整個流程。在實際應用中,往往需要保存大量‘備忘發起角色’的曆史狀態。這時就要對‘備忘錄管理者角色’進行改造,最簡單的方式就是采用容器來按照順序存放備忘錄角色。這樣就可以很好的實現undo、redo功能了。”
(本章完)