學習JavaScript設計模式之觀察者模式_javascript技巧

來源:互聯網
上載者:User

一、定義

觀察者模式(發布-訂閱模式):其定義對象間一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都將得到通知。
在JavaScript中,一般使用事件模型來替代傳統的觀察者模式。
好處:

  • (1)可廣泛應用於非同步編程中,是一種替代傳遞迴調函數的方案。
  • (2)可取代對象之間硬式編碼通知機制,一個對象不用再顯示地調用另外一個對象的某個介面。兩對象輕鬆解耦。

二、DOM事件–觀察者模式典例

需要監控使用者點擊document.body的動作,但是我們沒有辦法預知使用者將在什麼時間點擊。
所以,我們訂閱document.body上的click事件,當body節點被點擊時,body節點便向訂閱者發布這個訊息!

document.body.addEventListener("click", function() {  console.log(1);}, false);// 可以多個訂閱者document.body.addEventListener("click", function() {  console.log(2);}, false);doucment.body.click();

某網站有header頭部、nav導航、訊息列表等模組。這幾個模組的渲染都需要擷取使用者登陸資訊。
(1)一般寫法:

$.ajax({  url: './login',  type: 'post',  contentType: 'application/json',  dataType:'json',  success: function(data) {    if(data.status === "success") {      // 登入成功,渲染header、nav      header.setInfo(data.headerInfo);      nav.setInfo(data.navInfo);    }  }});

(2)使用觀察者模式,很輕鬆解耦!

$.ajax({  ...,  success: function(data) {    if(data.status === "success") {      // 登入成功,發布登陸成功訊息      login.trigger("loginsuccess", data);    }  }});var header = (function() {  // 監聽訊息  login.listen("loginsuccess", function(data){    header.setInfo(data.headerInfo);  });  return {    setInfo: function(data) {      console.log("設定header資訊");    }  };})();var nav = (function() {  login.listen("loginsuccess", function(data){    nav.setInfo(data.navInfo);  });  return {    setInfo: function(data) {      console.log("設定nav資訊");    }  }})();

三、通用觀察者模式

/* * 樣本: * Event.create("namespace1").listen('click', function(a){ *   console.log(a); * }); * Event.create("namespace1").trigger("click", 1); */var Event = (function() {  var global = this,    Event,    _default = 'default';  Event = function() {    var _listen,      _trigger,      _remove,      _slice = Array.prototype.slice,      _shift = Array.prototype.shift,      _unshift = Array.prototype.unshift,      namespaceCache = [],      _create,      find,      each = function( ary, fn) {        var ret;        for(var i = 0, l = ary.length; i < l; i++) {          var n = ary[i];          ret = fn.call(n, i, n);        }        return ret;      };    // 訂閱    _listen = function(key, fn, cache) {      if(!cache[key]) {        cache[key] = [];      }      cache[key].push(fn);    };    // 移除訂閱    _remove = function(key, cache, fn) {      if(cache[key]) {        if(fn) {          for(var i = cache[key].length; i >=0; i++) {            if(cache[key][i] === fn) {              cache[key].splice(i, 1);            }          }        }else {          cache[key] = [];        }      }    };    // 發布    _trigger = function() {     var cache = _shift.call(arguments),       key = _shift.call(arguments),       args = arguments,       _self = this,       ret,       stack = cache[key];      if(!stack || !stack.length) {        return;      }      return each(stack, function() {        return this.apply(_self, args);      });    };    // 建立命名空間    _create = function(namespace) {      var namespace = namespace || _default;      var cache = {},        offlineStack = [], // 離線事件        ret = {          listen: function (key, fn, last) {            _listen(key, fn, cache);            if (offlineStack == null) {              return;            }            if (last === 'last') {              offlineStack.length && offlineStack.pop()();            } else {              each(offlineStack, function () {                this();              });            }            offlineStack = null;          },          one: function (key, fn, last) {            _remove(key, cache);            this.listen(key, fn, last);          },          remove: function(key, fn, last) {            _remove(key, cache, fn);          },          trigger: function() {            var fn,              args,              _self = this;            _unshift.call(arguments, cache);            args = arguments;            fn = function() {              return _trigger.apply(_self, args);            };            if(offlineStack) {              return offlineStack.push(fn);            }            return fn;          }        };        return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret;      };    return {      create: _create,      one: function(key, fn, last) {        var event = this.create();        event.one(key, fn, last);      },      remove: function(key, fn) {        var event = this.create();        event.remove(key, fn);      },      listen: function(key, fn, last) {        var event = this.create();        event.listen(key, fn, last);      },      trigger: function() {        var event = this.create();        event.trigger.apply(this, arguments);      }    };  }();  return Event;})();

希望本文所述對大家學習javascript程式設計有所協助。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.