標籤:ceo 靜態 觀察 for logs cal 作用 function remove
觀察者模式,又稱發布-訂閱模式或訊息機制,定義了一種依賴關係,解決了主題對象與觀察者之間功能的耦合。
通過運用觀察者模式,可以解決團隊開發中的模組間通訊問題,這是模組間解耦的一種可行方案。
首先,我們來把觀察者對象建立處理,它有一個訊息容器和三個方法,分別是訂閱訊息方法、發送訂閱訊息的方法和取消訂閱訊息的方法。如下:
// 將觀察者放在閉包中,當頁面載入就立即執行var Observer = (function () { // 將訊息容器做為靜態私人變數,防止訊息佇列泄露而被篡改 var _messages = {}; return { regist: function () {}, // 註冊訊息 fire: function () {}, // 發布訊息 remove: function () {} // 取消訊息 };})();
現在,觀察者的雛形已經出來了,我們接下來的事情就是一步步實現這三個方法。
1. 註冊訊息的作用是將訂閱者的訊息推入到訊息佇列中,因此我們需要接受兩個參數:訊息類型和相應的處理動作。
在推入到訊息佇列時,如果此訊息不存在則應該建立一個訊息類型並將該訊息放入訊息佇列中;如果此訊息存在則應該將訊息執行方法推入改訊息對應的執行方法隊列中,這麼做的目的是保證多 個模組註冊同一則訊息時能順利執行。
regist: function (type, fn) { if (typeof _messages[type] === ‘undefined‘) { _messages[type] = [fn]; // 若此訊息不存在,則建立一個訊息容器 } else { _messages[type].push(fn); // 訊息存在,則將動作方法推入該訊息對應的動作執行序列中 }}
2. 發布訊息的功能是,當觀察者發布一個訊息時,會將所有訂閱者訂閱的訊息依次執行。故應該接受兩個參數:訊息類型和動作執行時要傳遞的參數。
在執行訊息動作隊列之前對訊息存在的校正是很有必要的,然後遍曆訊息執行方法隊列,並依次執行。
fire: function (type, args) { if (!_messages[type]) { return; }; var events = { type: type, args: args || {} }; for (var i = 0, len = _messages[type].length; i < len; i++) { _messages[type][i].call(this, args); };},
3. 登出訊息的功能是將訂閱者登出的訊息從訊息佇列中清除掉,因此我們可以傳遞兩個參數:訊息類型和動作函數。
如果只傳遞訊息類型參數,則登出所有訂閱此訊息類型的動作函數,
若兩者都傳遞,則只登出此訊息類型的當前傳遞參數的動作函數。
當然為了避免刪除訊息動作時訊息不存在的情況出現,對訊息佇列中訊息的存在性校正也是很有必要的。
remove: function (type, fn) { if (!fn) { _messages[type] = null; return; }; if (_messages[type] instanceof Array) { var i = _messages[type].length - 1; for (; i >= 0; i--) { _messages[type][i] === fn && _messages[type].splice(i, 1); }; }}
至此,觀察者模式就實現完啦!可以稍微測試一下:
var fn1 = function () { console.log(1);}var fn2 = function () { console.log(2);}Observer.regist(‘test‘, fn1);Observer.regist(‘test‘, fn2);Observer.fire(‘test‘); // 1 2Observer.remove(‘test‘, fn1);Observer.fire(‘test‘); // 2
JavaScript設計模式——觀察者模式