談?wù)動(dòng)^察者模式和發(fā)布訂閱模式

在網(wǎng)上看到許多關(guān)于觀察者模式和發(fā)布訂閱模式的博文,發(fā)現(xiàn)很多人都認(rèn)為觀察者模式即發(fā)布訂閱模式,經(jīng)過(guò)進(jìn)一步的學(xué)習(xí)和理解,我認(rèn)為觀察者模式和發(fā)布訂閱模式還是有一些區(qū)別的,下面談?wù)勎覍?duì)觀察者模式和發(fā)布訂閱模式的理解「PS:歡迎各路大神指正」。

觀察者模式(Observer)

觀察者模式指的是一個(gè)對(duì)象(Subject)維持一系列依賴于它的對(duì)象(Observer),當(dāng)有關(guān)狀態(tài)發(fā)生變更時(shí) Subject 對(duì)象則通知一系列 Observer 對(duì)象進(jìn)行更新。

在觀察者模式中,Subject 對(duì)象擁有添加、刪除和通知一系列 Observer 的方法等等,而 Observer 對(duì)象擁有更新方法等等。

在 Subject 對(duì)象添加了一系列 Observer 對(duì)象之后,Subject 對(duì)象則維持著這一系列 Observer 對(duì)象,當(dāng)有關(guān)狀態(tài)發(fā)生變更時(shí) Subject 對(duì)象則會(huì)通知這一系列 Observer 對(duì)象進(jìn)行更新。

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

上述代碼中,我們創(chuàng)建了 Subject 對(duì)象和兩個(gè) Observer 對(duì)象,當(dāng)有關(guān)狀態(tài)發(fā)生變更時(shí)則通過(guò) Subject 對(duì)象的 notify 方法通知這兩個(gè) Observer 對(duì)象,這兩個(gè) Observer 對(duì)象通過(guò) update 方法進(jìn)行更新。

在 Subject 對(duì)象添加了一系列 Observer 對(duì)象之后,還可以通過(guò) remove 方法移除某個(gè) Observer 對(duì)象對(duì)它的依賴。

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
發(fā)布訂閱模式(Publisher && Subscriber)

發(fā)布訂閱模式指的是希望接收通知的對(duì)象(Subscriber)基于一個(gè)主題通過(guò)自定義事件訂閱主題,被激活事件的對(duì)象(Publisher)通過(guò)發(fā)布主題事件的方式通知各個(gè)訂閱該主題的 Subscriber 對(duì)象。

let pubSub = {
  list:{},
  subscribe:function(key,fn){  // 訂閱
    if (!this.list[key]) {
      this.list[key] = [];
    }
    this.list[key].push(fn);
  },
  publish:function(){  // 發(fā)布
    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 主題來(lái)自定義事件,發(fā)布是通過(guò) name 和 sex 主題并傳入自定義事件的參數(shù),最終觸發(fā)了特定主題的自定義事件。

可以通過(guò) unSubscribe 方法取消特定主題的訂閱。

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');  // 這個(gè)主題被取消訂閱了
pubSub.publish('sex', 'male');  // your sex is male
觀察者模式 VS 發(fā)布訂閱模式
觀察者模式與發(fā)布訂閱模式

觀察者模式與發(fā)布訂閱模式都是定義了一個(gè)一對(duì)多的依賴關(guān)系,當(dāng)有關(guān)狀態(tài)發(fā)生變更時(shí)則執(zhí)行相應(yīng)的更新。

不同的是,在觀察者模式中依賴于 Subject 對(duì)象的一系列 Observer 對(duì)象在被通知之后只能執(zhí)行同一個(gè)特定的更新方法,而在發(fā)布訂閱模式中則可以基于不同的主題去執(zhí)行不同的自定義事件。相對(duì)而言,發(fā)布訂閱模式比觀察者模式要更加靈活多變。

我認(rèn)為,觀察者模式和發(fā)布訂閱模式本質(zhì)上的思想是一樣的,而發(fā)布訂閱模式可以被看作是觀察者模式的一個(gè)進(jìn)階版。

設(shè)計(jì)模式只是一種思想,某一種設(shè)計(jì)模式都可以有很多種不同的實(shí)現(xiàn)方式,各種實(shí)現(xiàn)都有其優(yōu)劣之分,具體的實(shí)現(xiàn)方式需要基于不同的業(yè)務(wù)場(chǎng)景。上述是我對(duì)觀察者模式和發(fā)布訂閱模式學(xué)習(xí)之后的一些理解,望指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 設(shè)計(jì)模式概述 在學(xué)習(xí)面向?qū)ο笃叽笤O(shè)計(jì)原則時(shí)需要注意以下幾點(diǎn):a) 高內(nèi)聚、低耦合和單一職能的“沖突”實(shí)際上,這兩者...
    彥幀閱讀 3,898評(píng)論 0 14
  • 1 場(chǎng)景問(wèn)題# 1.1 訂閱報(bào)紙的過(guò)程## 來(lái)考慮實(shí)際生活中訂閱報(bào)紙的過(guò)程,這里簡(jiǎn)單總結(jié)了一下,訂閱報(bào)紙的基本流程...
    七寸知架構(gòu)閱讀 4,814評(píng)論 5 57
  • 【學(xué)習(xí)難度:★★★☆☆,使用頻率:★★★★★】直接出處:觀察者模式梳理和學(xué)習(xí):https://github.com...
    BruceOuyang閱讀 1,678評(píng)論 1 5
  • 天色漸漸陰暗了下來(lái),六月的天,娃兒的臉,說(shuō)變就變,剛剛還晴空萬(wàn)里,這一會(huì)兒就狂風(fēng)大作,噼里啪啦的大雨滴砸在一對(duì)年輕...
    冷劍書(shū)生閱讀 427評(píng)論 0 0
  • 文/白襯衣書(shū)生 有多久沒(méi)在操場(chǎng)上跑步了,可能是從上大學(xué)開(kāi)始吧,也有可能是沒(méi)了早操和老師的強(qiáng)制要求以后。 跑步。有人...
    風(fēng)先生情感咨詢閱讀 343評(píng)論 0 0

友情鏈接更多精彩內(nèi)容