iT邦幫忙

DAY 8
2

Javascript面面觀系列 第 8

Javascript面面觀:核心篇《模式-observer》

Observer模式是GOF design pattern裡面很基本的模式,他的目的主要是讓一個物件狀態改變時,多個相關物件可以被通知。Java就大量使用這個模式來處理事件。
結構
Javascript中,Observer的實作方法大致上符合GOF裡面提到的方法。以下用一個剛好可以滿足Observer的需要的功能的簡單的例子來示範;裡面用了三個物件:Observer、Observable、CustomEvent來協作,Observer把它做成一個像是CustomEvent的內部物件用來做事件管理的單位,事件透過CustomEvent來註冊,Observable狀態改變時,就會通知Observer:

<script>
(function(){
	function Observer(fn, type) {
		this.uid = this.toString() + new Date().getTime();
		this.update = function(e) {
			if (e.type == type) {
				fn(e);
			}
		};
	}
	$ = {};
	$.EventType = {
		noEvent: 0,
		Type1: 1,
		Type2: 2
	};	
	$.CustomEvent = new (function() {
		var subscribed = {};
		this.registerEvent = function (o, fn, type) {
			var ob = new Observer(fn, type);
			o.subscribe(ob);
			subscribed[ob.uid] = ob;
			return ob.uid;
		};
		this.unregisterEvent = function (o, uid) {
			o.unsubscribe(subscribed[uid]);
			delete subscribed[uid];
		};
	})();
	$.Observable = function () {
		var subscribers = {};
		var state = $.EventType.noEvent;
		this.notify = function() {
			for (var i in subscribers) {
				subscribers[i].update({type: state});
			}
		};
		this.subscribe = function(s, type) {
			if (!subscribers[s.uid]) {
				subscribers[s.uid] = s;
			}
		};
		this.unsubscribe = function(s) {
			if (subscribers[s.uid]) {
				delete subscribers[s.uid];
			}
		};
		this.getState = function() {return state;};
		this.setState = function(s) {
			state = s;
			this.notify();
		};
	};
})();
var obj = new $.Observable();
var eid = $.CustomEvent.registerEvent(
	obj,
	function(e){alert("event type of: " + e.type);},
	$.EventType.Type1);
obj.setState($.EventType.Type1);
obj.setState($.EventType.Type2);
$.CustomEvent.unregisterEvent(obj, eid);
obj.setState($.EventType.Type1);
</script>

以細節來說還有進步空間,但是可以看到簡單的Observer模式運作的全貌。

應用
在Javascript中,Observer模式最常用的地方,恐怕還是用來管理自訂的事件。把上面的程式做一些調整,然後需要使用自訂事件的物件繼承Observable,接下來就可以透過CustomEvent來做自訂事件的管理。

例如YUI3,就定義了DomEVent、CustomEvent以及Event三個模組,其中DomEvent用來包裝DOM的事件、CustomEvent則應用Observer模式來實作自訂事件,最後Event使用facade模式把這兩個包裝成一致的介面。


上一篇
Javascript面面觀:核心篇《模式-lazy load》
下一篇
Javascript面面觀:核心篇《模式-fluent interface(cascade)》
系列文
Javascript面面觀30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
fillano
iT邦超人 1 級 ‧ 2009-10-20 11:00:21

從今天開始偷懶...

jamesjan iT邦高手 1 級 ‧ 2009-10-20 12:30:46 檢舉

那我應該從沒勤奮過...XD

我要留言

立即登入留言