用Javascript試作Memento Pattern
Wed, 23 Apr 2008 20:10:42 +0800GOF的Memento Pattern裡面用了三個類別來協作,分別是Caretaker、Originator以及Memento。Originator依賴Memento來儲存狀態,並將Memento存在Caretaker,Caretaker操作Originator時,可以跟Originator取得Menento來存放,等到需要回復操作時,把Memento傳給Originator來回復他的狀態。
Caretaker對於Memento有存取的限制,在GoF的例子裡面,是把Originator指定為Memento的Friend類別,讓Originator可以存取Memento的getState,setState等私有方法,同時Memento的建構子也是私有的,所以只有透過Originator才能創建。
在Javascript中沒有Friend....倒是可以透過closure來讓Memento只有Originator才能創建,但是Memento的setState以及getState方法,就沒有辦法建立存取的權限,所以Caretaker收到memento時,其實可以直接使用他的....get/setState方法,這樣做就沒意義了。
GoF的例子裡面,Originator是一個Singleton,這個倒是可以用匿名函數的closure做出來就是了。
以下是測試的程式:
//試作memento模式,另外也用closure做出一個singleton (function(){ var memento = function(state) { var _state = state; this.getState = function(obj) { return _state; } this.setState = function(obj, state) { _state = state; } } var _instance = null; getOriginator = function() { if(_instance==null) { _instance = new originator(); } return _instance; } var originator = function() { var _state = 0; var _memento = null; this.createMemento = function() { _memento = new memento(_state); return _memento; } this.setMemento = function(obj) { if(obj instanceof memento) { _state = obj.getState(); } } this.getState = function() { return _state; } this.setState = function(state) { _state = state; } } })(); function caretaker() { var _memento = null; this.execute = function(state) { var _originator = getOriginator(); _memento = _originator.createMemento(); _originator.setState(state); alert(_originator.getState()); } this.unexecute = function() { var _originator = getOriginator(); _originator.setMemento(_memento); alert(_originator.getState()); } } var a = new caretaker(); a.execute(3); a.execute(5); a.unexecute();
所以結論是....失敗了。
2008-5-1 補充
後來用closure模擬出friend的效果,完整的memento pattern試作請見用closure模擬friend宣告的效果。