用Javascript試作Memento Pattern

 Wed, 23 Apr 2008 20:10:42 +0800

GOF的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宣告的效果