DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> 學習JavaScript設計模式之觀察者模式
學習JavaScript設計模式之觀察者模式
編輯:關於JavaScript     

一、定義

觀察者模式(發布-訂閱模式):其定義對象間一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴於它的對象都將得到通知。
在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程序設計有所幫助。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved