觀察者模式(Observer)
觀察者模式指的是一個對象(Subject)維持一系列依賴於它的對象(Observer),當有關狀態發生變更時 Subject 對象則通知一系列 Observer 對象進行更新。
在觀察者模式中,Subject 對象擁有添加、刪除和通知一系列 Observer 的方法等等,而 Observer 對象擁有更新方法等等。
在 Subject 對象添加了一系列 Observer 對象之后,Subject 對象則維持着這一系列 Observer 對象,當有關狀態發生變更時 Subject 對象則會通知這一系列 Observer 對象進行更新。
function Subject(){ this.observers = []; } Subject.prototype = { add:function(observer){ // 添加 this.observers.push(observer); }, remove:function(observer){ // 刪除 var observers = this.observers; for(var i = 0;i < observers.length;i++){ if(observers[i] === observer){ observers.splice(i,1); } } }, notify:function(){ // 通知 var observers = this.observers; for(var i = 0;i < observers.length;i++){ observers[i].update(); } } } function Observer(name){ this.name = name; } Observer.prototype = { update:function(){ // 更新 console.log('my name is '+this.name); } } var sub = new Subject(); var obs1 = new Observer('ttsy1'); var obs2 = new Observer('ttsy2'); sub.add(obs1); sub.add(obs2); sub.notify(); //my name is ttsy1、my name is ttsy2
上述代碼中,我們創建了 Subject 對象和兩個 Observer 對象,當有關狀態發生變更時則通過 Subject 對象的 notify 方法通知這兩個 Observer 對象,這兩個 Observer 對象通過 update 方法進行更新。
在 Subject 對象添加了一系列 Observer 對象之后,還可以通過 remove 方法移除某個 Observer 對象對它的依賴。
var sub = new Subject(); var obs1 = new Observer('ttsy1'); var obs2 = new Observer('ttsy2'); sub.add(obs1); sub.add(obs2); sub.remove(obs2); sub.notify(); //my name is ttsy1
發布訂閱模式(Publisher && Subscriber)
發布訂閱模式指的是希望接收通知的對象(Subscriber)基於一個主題通過自定義事件訂閱主題,被激活事件的對象(Publisher)通過發布主題事件的方式通知各個訂閱該主題的 Subscriber 對象。
let pubSub = { list:{}, subscribe:function(key,fn){ // 訂閱 if (!this.list[key]) { this.list[key] = []; } this.list[key].push(fn); }, publish:function(){ // 發布 let arg = arguments; let key = [].shift.call(arg); let fns = this.list[key]; if(!fns || fns.length<=0) return false; for(var i=0,len=fns.length;i<len;i++){ fns[i].apply(this, arg); } }, unSubscribe(key) { // 取消訂閱 delete this.list[key]; } }; pubSub.subscribe('name', (name) => { console.log('your name is ' + name); }); pubSub.subscribe('sex', (sex) => { console.log('your sex is ' + sex); }); pubSub.publish('name', 'ttsy1'); // your name is ttsy1 pubSub.publish('sex', 'male'); // your sex is male
上述代碼的訂閱是基於 name 和 sex 主題來自定義事件,發布是通過 name 和 sex 主題並傳入自定義事件的參數,最終觸發了特定主題的自定義事件。
可以通過 unSubscribe 方法取消特定主題的訂閱。
pubSub.subscribe('name', (name) => {
pubSub.subscribe('name', (name) => { console.log('your name is ' + name); }); pubSub.subscribe('sex', (sex) => { console.log('your sex is ' + sex); }); pubSub.unSubscribe('name'); pubSub.publish('name', 'ttsy1'); // 這個主題被取消訂閱了 pubSub.publish('sex', 'male'); // your sex is male
觀察者模式 VS 發布訂閱模式
觀察者模式與發布訂閱模式都是定義了一個一對多的依賴關系,當有關狀態發生變更時則執行相應的更新。
不同的是,在觀察者模式中依賴於 Subject 對象的一系列 Observer 對象在被通知之后只能執行同一個特定的更新方法,而在發布訂閱模式中則可以基於不同的主題去執行不同的自定義事件。相對而言,發布訂閱模式比觀察者模式要更加靈活多變。
我認為,觀察者模式和發布訂閱模式本質上的思想是一樣的,而發布訂閱模式可以被看作是觀察者模式的一個進階版。
設計模式只是一種思想,某一種設計模式都可以有很多種不同的實現方式,各種實現都有其優劣之分,具體的實現方式需要基於不同的業務場景。上述是我對觀察者模式和發布訂閱模式學習之后的一些理解,望指正。