javascript觀察者模式

來源:互聯網
上載者:User

觀察者模式又稱發布-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents)模式。

觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽一個主題對象。這個主題對象在狀態上發生變化時,會通知所有觀察者,使它們能夠自動更新自己。

下面拿老外的例子改一改,練練手。

      var dom = {        each : function(obj,fn,score){          for(var key in obj){            if(obj.hasOwnProperty(key))              fn.call(score,obj[key],key,obj)          }        }      };      dom.each({        indexOf: function (el, index) {          var n = this.length,          i = index == null ? 0 : index < 0 ? Math.max(0, n + index) : index;          for (; i < n; i++)            if (i in this && this[i] === el) return i;          return -1;        },        //移除 Array 對象中指定位置的元素。        removeAt: function (index) {          return this.splice(index, 1)        },        //移除 Array 對象中某個元素的第一個匹配項。        remove: function (item) {          var index = this.indexOf(item);          if (index !== -1) this.removeAt(index);          return item;        }      },function(method,name){        if(!Array.prototype[name])          Array.prototype[name] = method;      });      /* 訂閱者介面 */      var Observer = function() {        //觀察者要實現的方法        this.update = function() {throw "此方法必須被實現!"}      }      /* 發行者介面 */      var Subject = function() {        this.observers = [];      }      Subject.prototype = {        //如果狀態發生改變,通知所有觀察者調用其update方法        notifyObservers : function(context) {          for(var i = 0, n = this.observers.length; i < n; i++) {            this.observers[i].update(context);          }        },        // 添加訂閱者        attach : function(observer){          if(!observer.update) throw 'Wrong observer';          this.observers.push(observer);        },        /* 移除訂閱者 */        detach : function(observer) {          if(!observer.update) { throw 'Wrong observer'; }          this.observers.remove(observer);        }      }      //實現介面      var implement = function(Concrete,Interface){        for(var prop in  Interface) {          Concrete[prop] = Interface[prop];        }      }      /***************** 發行者的實作類別 ***********************/      var mainCheck = document.createElement("input");      mainCheck.type = 'checkbox';      mainCheck.id = 'MainCheck';      mainCheck.style.cssText = 'border:1px solid red';      implement( mainCheck,new Subject());      /* 當點擊按鈕的時候 給相關的觀察者發送通知. 觀察者接收到通知的時候 改變狀態 */      mainCheck['onclick'] = function(){        this.notifyObservers(this.checked)      }          document.body.appendChild(mainCheck);      /********************* 訂閱者的實作類別 *****************************/      var obsCheck1 = document.createElement('input');      var obsCheck2 = document.createElement('input');      obsCheck1.type = 'checkbox';      obsCheck1.id = 'Obs1';      document.body.appendChild(obsCheck1);      obsCheck2.type = 'checkbox';      obsCheck2.id = 'Obs2';      document.body.appendChild(obsCheck2);      implement( obsCheck1,new Observer());      implement( obsCheck2,new Observer());      /* 必須實現它們的具體update方法 */      obsCheck1.update = function(value) {        this.checked = value;      }      obsCheck2.update = function(value) {        this.checked = value;      }      // 將發行者和訂閱者(觀察者)關聯      mainCheck.attach(obsCheck1);      mainCheck.attach(obsCheck2);

<br /><!doctype html><br /><html><br /> <head><br /> <title>javascript 觀察者模式 by 司徒正美</title><br /> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /><br /> </head><br /> <body><br /> <script type="text/javascript"><br /> var dom = {<br /> each : function(obj,fn,score){<br /> for(var key in obj){<br /> if(obj.hasOwnProperty(key))<br /> fn.call(score,obj[key],key,obj)<br /> }<br /> }<br /> };<br /> dom.each({<br /> indexOf: function (el, index) {<br /> var n = this.length,<br /> i = index == null ? 0 : index < 0 ? Math.max(0, n + index) : index;<br /> for (; i < n; i++)<br /> if (i in this && this[i] === el) return i;<br /> return -1;<br /> },<br /> //移除 Array 對象中指定位置的元素。<br /> removeAt: function (index) {<br /> return this.splice(index, 1)<br /> },<br /> //移除 Array 對象中某個元素的第一個匹配項。<br /> remove: function (item) {<br /> var index = this.indexOf(item);<br /> if (index !== -1) this.removeAt(index);<br /> return item;<br /> }<br /> },function(method,name){<br /> if(!Array.prototype[name])<br /> Array.prototype[name] = method;<br /> });</p><p> /* 訂閱者介面 */<br /> var Observer = function() {<br /> //觀察者要實現的方法<br /> this.update = function() {throw "此方法必須被實現!"}<br /> }<br /> /* 發行者介面 */<br /> var Subject = function() {<br /> this.observers = [];<br /> }<br /> Subject.prototype = {<br /> //如果狀態發生改變,通知所有觀察者調用其update方法<br /> notifyObservers : function(context) {<br /> for(var i = 0, n = this.observers.length; i < n; i++) {<br /> this.observers[i].update(context);<br /> }<br /> },<br /> // 添加訂閱者<br /> attach : function(observer){<br /> if(!observer.update) throw 'Wrong observer';<br /> this.observers.push(observer);<br /> },<br /> /* 移除訂閱者 */<br /> detach : function(observer) {<br /> if(!observer.update) { throw 'Wrong observer'; }<br /> this.observers.remove(observer);<br /> }<br /> }<br /> //實現介面<br /> var implement = function(Concrete,Interface){<br /> for(var prop in Interface) {<br /> Concrete[prop] = Interface[prop];<br /> }<br /> }</p><p> /***************** 發行者的實作類別 ***********************/<br /> var mainCheck = document.createElement("input");<br /> mainCheck.type = 'checkbox';<br /> mainCheck.id = 'MainCheck';<br /> mainCheck.style.cssText = 'border:1px solid red';<br /> implement( mainCheck,new Subject());<br /> /* 當點擊按鈕的時候 給相關的觀察者發送通知. 觀察者接收到通知的時候 改變狀態 */<br /> mainCheck['onclick'] = function(){<br /> this.notifyObservers(this.checked)<br /> }</p><p> document.body.appendChild(mainCheck);</p><p> /********************* 訂閱者的實作類別 *****************************/<br /> var obsCheck1 = document.createElement('input');<br /> var obsCheck2 = document.createElement('input');<br /> obsCheck1.type = 'checkbox';<br /> obsCheck1.id = 'Obs1';<br /> document.body.appendChild(obsCheck1);</p><p> obsCheck2.type = 'checkbox';<br /> obsCheck2.id = 'Obs2';<br /> document.body.appendChild(obsCheck2);<br /> implement( obsCheck1,new Observer());<br /> implement( obsCheck2,new Observer());</p><p> /* 必須實現它們的具體update方法 */<br /> obsCheck1.update = function(value) {<br /> this.checked = value;<br /> }</p><p> obsCheck2.update = function(value) {<br /> this.checked = value;<br /> }</p><p> // 將發行者和訂閱者(觀察者)關聯<br /> mainCheck.attach(obsCheck1);<br /> mainCheck.attach(obsCheck2);</p><p> </script><br /> </body><br /></html><br />

運行代碼

這東西比較簡單,涉及兩個陣營。一個是發行者,你把它當成伺服器端就是,肯定要做比用戶端更多的事。為此,發行者要擁有訂閱者的列表,支援添加或刪除它們,當自己更新時,同步更新訂閱者相應的東西。訂閱者則不需要做許多事,只要提供一個update方法,供發行者調用就是。寫這個時,我總是想起RSS,我的部落格更新,便立即更新訂閱者google reader上的內容。不過,javascript擁有DOM過門的事件系統,除非涉及的幾個對象都不是元素節點,一般很少自己重新造輪子。

註:本文為rightjs學習筆記的一部分。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.