設計模式」(Design Pattern)是針對編程中常常出現的、具備共性的問題,所提出的解決方法。著名的《設計模式》一書一共提出了23種模式。編程
它定義了一種對象間一對多的關係,多個訂閱者對象將本身的「主題/事件」註冊進一個目標對象,當目標對象狀態發生改變時,只須要去執行對應訂閱者註冊的 "主題/事件" 就好了。這是一種鬆耦合的狀態。目標對象不用關心任何訂閱者的狀況, 只須要發佈註冊在本身身上的事件就好了。
訂閱者只管註冊 目標對象只管發佈 互不影響
代碼實現:設計模式
let event = { clientList: {}, listen (key, fn) { if (!this.clientList[key]) { this.clientList[key] = [] } this.clientList[key].push(fn) // 訂閱的消息添加進緩存列表 }, trigger (type, money) { let fns = this.clientList[type] if (!fns || fns.length === 0) { // 若是沒有綁定對應的消息 return false } fns.forEach(fn => { fn.apply(this, [money]) }) } } // 再定義一個installEvent函數,用於給全部對象動態安裝發佈-訂閱功能 // 如:另外一家售樓處也想要這個功能,就能夠調用這個註冊了,不用再寫多一次這段代碼 let installEvent = obj => { for (let i in event) { obj[i] = event[i] } } // 給售樓處對象salesOffices動態增長髮布-訂閱功能 let salesOffices = {} installEvent(salesOffices) // 小明訂閱信息 salesOffices.listen('squareMeter88', price => { console.log('小明,你看中的88平方的房子,價格=' + price) }) // 小光訂閱信息 salesOffices.listen('squareMeter88', price => { console.log('小光,你看中的88平方的房子,價格=' + price) }) // 小紅訂閱信息 salesOffices.listen('squareMeter100', price => { console.log('小紅,你看中的100平方的房子,價格=' + price) }) salesOffices.trigger('squareMeter88', 2000000) salesOffices.trigger('squareMeter100', 2500000)
觀察者模式與發佈訂閱最大的區別是訂閱者註冊的是本身自己,再也不是註冊 「主題/事件」,當目標對象狀態發生改變時,會調用自身的通知方法,從而調用註冊在自身的訂閱者的更新方法。緩存
//觀察者列表 function ObserverList(){ this.observerList = []; } ObserverList.prototype.add = function( obj ){ return this.observerList.push( obj ); }; ObserverList.prototype.count = function(){ return this.observerList.length; }; ObserverList.prototype.get = function( index ){ if( index > -1 && index < this.observerList.length ){ return this.observerList[ index ]; } }; ObserverList.prototype.indexOf = function( obj, startIndex ){ var i = startIndex; while( i < this.observerList.length ){ if( this.observerList[i] === obj ){ return i; } i++; } return -1; }; ObserverList.prototype.removeAt = function( index ){ this.observerList.splice( index, 1 ); }; //目標 function Subject(){ this.observers = new ObserverList(); } Subject.prototype.addObserver = function( observer ){ this.observers.add( observer ); }; Subject.prototype.removeObserver = function( observer ){ this.observers.removeAt( this.observers.indexOf( observer, 0 ) ); }; Subject.prototype.notify = function( context ){ var observerCount = this.observers.count(); for(var i=0; i < observerCount; i++){ this.observers.get(i).update( context ); } }; //觀察者 function Observer(){ this.update = function(){ // ... }; }
發佈訂閱模式實現了更細粒度化的管理,觀察者模式當目標對象狀態變化時會通知全部訂閱者,而發佈訂閱則會經過調度中心執行具體的訂閱者註冊的 "主題/事件",發佈訂閱更鬆耦合一些。app