最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談發(fā)布訂閱模式與觀察者模式

 更新時(shí)間:2019年04月09日 10:06:46   作者:hfhan  
這篇文章主要介紹了淺談發(fā)布訂閱模式與觀察者模式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

背景

設(shè)計(jì)模式并非是軟件開發(fā)的專業(yè)術(shù)語,實(shí)際上,“模式”最早誕生于建筑學(xué)。

設(shè)計(jì)模式的定義是:在面向?qū)ο筌浖O(shè)計(jì)過程中針對特定問題的簡潔而優(yōu)雅的解決方案。通俗一點(diǎn)說,設(shè)計(jì)模式是在某種場合下對某個(gè)問題的一種解決方案。如果再通俗一點(diǎn)說,設(shè)計(jì)模式就是給面向?qū)ο筌浖_發(fā)中的一些好的設(shè)計(jì)取個(gè)名字。

這些“好的設(shè)計(jì)”并不是誰發(fā)明的,而是早已存在于軟件開發(fā)中。一個(gè)稍有經(jīng)驗(yàn)的程序員也許在不知不覺中數(shù)次使用過這些設(shè)計(jì)模式。GoF(Gang of Four--四人組,《設(shè)計(jì)模式》幾位作者)最大的功績是把這些“好的設(shè)計(jì)”從浩瀚的面向?qū)ο笫澜缰刑暨x出來,并且給予它們一個(gè)好聽又好記的名字。

設(shè)計(jì)模式并不直接用來完成代碼的編寫,而是描述在各種不同情況下,要怎么解決問題的一種方案,他不是一個(gè)死的機(jī)制,他是一種思想,一種寫代碼的形式。每種語言對于各種設(shè)計(jì)模式都有他們自己的實(shí)現(xiàn)方式,對于某些設(shè)計(jì)模式來說,可能在某些語言下并不適用,比如工廠方法模式對于javascript。模式應(yīng)該用在正確的地方。而哪些才算正確的地方,只有在我們深刻理解了模式的意圖之后,再結(jié)合項(xiàng)目的實(shí)際場景才會(huì)知道。。

模式的社區(qū)一直在發(fā)展。GoF在1995年提出了23種設(shè)計(jì)模式,但模式不僅僅局限于這23種,后面增加到了24種。在這20多年的時(shí)間里,也許有更多的模式已經(jīng)被人發(fā)現(xiàn)并總結(jié)了出來,比如一些JavaScript 圖書中會(huì)提到模塊模式、沙箱模式等。這些“模式”能否被世人公認(rèn)并流傳下來,還有待時(shí)間驗(yàn)證。

觀察者模式(Observer Pattern)

觀察者模式定義了對象間的一種一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對象都將得到通知,并自動(dòng)更新。觀察者模式屬于行為型模式,行為型模式關(guān)注的是對象之間的通訊,觀察者模式就是觀察者和被觀察者之間的通訊。

觀察者模式有一個(gè)別名叫“發(fā)布-訂閱模式”,或者說是“訂閱-發(fā)布模式”,訂閱者和訂閱目標(biāo)是聯(lián)系在一起的,當(dāng)訂閱目標(biāo)發(fā)生改變時(shí),逐個(gè)通知訂閱者。我們可以用報(bào)紙期刊的訂閱來形象的說明,當(dāng)你訂閱了一份報(bào)紙,每天都會(huì)有一份最新的報(bào)紙送到你手上,有多少人訂閱報(bào)紙,報(bào)社就會(huì)發(fā)多少份報(bào)紙,報(bào)社和訂報(bào)紙的客戶就是上面文章開頭所說的“一對多”的依賴關(guān)系。

發(fā)布訂閱模式(Pub-Sub Pattern)

其實(shí)24種基本的設(shè)計(jì)模式中并沒有發(fā)布訂閱模式,上面也說了,他只是觀察者模式的一個(gè)別稱。

但是經(jīng)過時(shí)間的沉淀,似乎他已經(jīng)強(qiáng)大了起來,已經(jīng)獨(dú)立于觀察者模式,成為另外一種不同的設(shè)計(jì)模式。

在現(xiàn)在的發(fā)布訂閱模式中,稱為發(fā)布者的消息發(fā)送者不會(huì)將消息直接發(fā)送給訂閱者,這意味著發(fā)布者和訂閱者不知道彼此的存在。在發(fā)布者和訂閱者之間存在第三個(gè)組件,稱為消息代理或調(diào)度中心或中間件,它維持著發(fā)布者和訂閱者之間的聯(lián)系,過濾所有發(fā)布者傳入的消息并相應(yīng)地分發(fā)它們給訂閱者。

舉一個(gè)例子,你在微博上關(guān)注了A,同時(shí)其他很多人也關(guān)注了A,那么當(dāng)A發(fā)布動(dòng)態(tài)的時(shí)候,微博就會(huì)為你們推送這條動(dòng)態(tài)。A就是發(fā)布者,你是訂閱者,微博就是調(diào)度中心,你和A是沒有直接的消息往來的,全是通過微博來協(xié)調(diào)的(你的關(guān)注,A的發(fā)布動(dòng)態(tài))。

觀察者模式和發(fā)布訂閱模式有什么區(qū)別?

我們先來看下這兩個(gè)模式的實(shí)現(xiàn)結(jié)構(gòu):

觀察者模式:觀察者(Observer)直接訂閱(Subscribe)主題(Subject),而當(dāng)主題被激活的時(shí)候,會(huì)觸發(fā)(Fire Event)觀察者里的事件。

發(fā)布訂閱模式:訂閱者(Subscriber)把自己想訂閱的事件注冊(Subscribe)到調(diào)度中心(Topic),當(dāng)發(fā)布者(Publisher)發(fā)布該事件(Publish topic)到調(diào)度中心,也就是該事件觸發(fā)時(shí),由調(diào)度中心統(tǒng)一調(diào)度(Fire Event)訂閱者注冊到調(diào)度中心的處理代碼。

我們再來看下這兩個(gè)模式的代碼案例:(獵人發(fā)布與訂閱任務(wù))

觀察者模式:

  //有一家獵人工會(huì),其中每個(gè)獵人都具有發(fā)布任務(wù)(publish),訂閱任務(wù)(subscribe)的功能
  //他們都有一個(gè)訂閱列表來記錄誰訂閱了自己
  //定義一個(gè)獵人類
  //包括姓名,級(jí)別,訂閱列表
  function Hunter(name, level){
    this.name = name
    this.level = level
    this.list = []
  }
  Hunter.prototype.publish = function (money){
    console.log(this.level + '獵人' + this.name + '尋求幫助')
    this.list.forEach(function(item, index){
      item(money)
    })
  }
  Hunter.prototype.subscribe = function (targrt, fn){
    console.log(this.level + '獵人' + this.name + '訂閱了' + targrt.name)
    targrt.list.push(fn)
  }
  
  //獵人工會(huì)走來了幾個(gè)獵人
  let hunterMing = new Hunter('小明', '黃金')
  let hunterJin = new Hunter('小金', '白銀')
  let hunterZhang = new Hunter('小張', '黃金')
  let hunterPeter = new Hunter('Peter', '青銅')
  
  //Peter等級(jí)較低,可能需要幫助,所以小明,小金,小張都訂閱了Peter
  hunterMing.subscribe(hunterPeter, function(money){
    console.log('小明表示:' + (money > 200 ? '' : '暫時(shí)很忙,不能') + '給予幫助')
  })
  hunterJin.subscribe(hunterPeter, function(){
    console.log('小金表示:給予幫助')
  })
  hunterZhang.subscribe(hunterPeter, function(){
    console.log('小張表示:給予幫助')
  })
  
  //Peter遇到困難,賞金198尋求幫助
  hunterPeter.publish(198)
  
  //獵人們(觀察者)關(guān)聯(lián)他們感興趣的獵人(目標(biāo)對象),如Peter,當(dāng)Peter有困難時(shí),會(huì)自動(dòng)通知給他們(觀察者)

發(fā)布訂閱模式:

  //定義一家獵人工會(huì)
  //主要功能包括任務(wù)發(fā)布大廳(topics),以及訂閱任務(wù)(subscribe),發(fā)布任務(wù)(publish)
  let HunterUnion = {
    type: 'hunt',
    topics: Object.create(null),
    subscribe: function (topic, fn){
      if(!this.topics[topic]){
         this.topics[topic] = []; 
      }
      this.topics[topic].push(fn);
    },
    publish: function (topic, money){
      if(!this.topics[topic])
         return;
      for(let fn of this.topics[topic]){
        fn(money)
      }
    }
  }
  
  //定義一個(gè)獵人類
  //包括姓名,級(jí)別
  function Hunter(name, level){
    this.name = name
    this.level = level
  }
  //獵人可在獵人工會(huì)發(fā)布訂閱任務(wù)
  Hunter.prototype.subscribe = function (topic, fn){
    console.log(this.level + '獵人' + this.name + '訂閱了狩獵' + topic + '的任務(wù)')
    HunterUnion.subscribe(topic, fn)
  }
  Hunter.prototype.publish = function (topic, money){
    console.log(this.level + '獵人' + this.name + '發(fā)布了狩獵' + topic + '的任務(wù)')
    HunterUnion.publish(topic, money)
  }
  
  //獵人工會(huì)走來了幾個(gè)獵人
  let hunterMing = new Hunter('小明', '黃金')
  let hunterJin = new Hunter('小金', '白銀')
  let hunterZhang = new Hunter('小張', '黃金')
  let hunterPeter = new Hunter('Peter', '青銅')
  
  //小明,小金,小張分別訂閱了狩獵tiger的任務(wù)
  hunterMing.subscribe('tiger', function(money){
    console.log('小明表示:' + (money > 200 ? '' : '不') + '接取任務(wù)')
  })
  hunterJin.subscribe('tiger', function(money){
    console.log('小金表示:接取任務(wù)')
  })
  hunterZhang.subscribe('tiger', function(money){
    console.log('小張表示:接取任務(wù)')
  })
  //Peter訂閱了狩獵sheep的任務(wù)
  hunterPeter.subscribe('sheep', function(money){
    console.log('Peter表示:接取任務(wù)')
  })
  
  //Peter發(fā)布了狩獵tiger的任務(wù)
  hunterPeter.publish('tiger', 198)
  
  //獵人們發(fā)布(發(fā)布者)或訂閱(觀察者/訂閱者)任務(wù)都是通過獵人工會(huì)(調(diào)度中心)關(guān)聯(lián)起來的,他們沒有直接的交流。

觀察者模式和發(fā)布訂閱模式最大的區(qū)別就是發(fā)布訂閱模式有個(gè)事件調(diào)度中心。

觀察者模式由具體目標(biāo)調(diào)度,每個(gè)被訂閱的目標(biāo)里面都需要有對觀察者的處理,這種處理方式比較直接粗暴,但是會(huì)造成代碼的冗余。

而發(fā)布訂閱模式中統(tǒng)一由調(diào)度中心進(jìn)行處理,訂閱者和發(fā)布者互不干擾,消除了發(fā)布者和訂閱者之間的依賴。這樣一方面實(shí)現(xiàn)了解耦,還有就是可以實(shí)現(xiàn)更細(xì)粒度的一些控制。比如發(fā)布者發(fā)布了很多消息,但是不想所有的訂閱者都接收到,就可以在調(diào)度中心做一些處理,類似于權(quán)限控制之類的。還可以做一些節(jié)流操作。

觀察者模式是不是發(fā)布訂閱模式

網(wǎng)上關(guān)于這個(gè)問題的回答,出現(xiàn)了兩極分化,有認(rèn)為發(fā)布訂閱模式就是觀察者模式的,也有認(rèn)為觀察者模式和發(fā)布訂閱模式是真不一樣的。

其實(shí)我不知道發(fā)布訂閱模式是不是觀察者模式,就像我不知道辨別模式的關(guān)鍵是設(shè)計(jì)意圖還是設(shè)計(jì)結(jié)構(gòu)(理念),雖然《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》一書中說了分辨模式的關(guān)鍵是意圖而不是結(jié)構(gòu)。

如果以結(jié)構(gòu)來分辨模式,發(fā)布訂閱模式相比觀察者模式多了一個(gè)中間件訂閱器,所以發(fā)布訂閱模式是不同于觀察者模式的;如果以意圖來分辨模式,他們都是實(shí)現(xiàn)了對象間的一種一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對象都將得到通知,并自動(dòng)更新,那么他們就是同一種模式,發(fā)布訂閱模式是在觀察者模式的基礎(chǔ)上做的優(yōu)化升級(jí)。

不過,不管他們是不是同一個(gè)設(shè)計(jì)模式,他們的實(shí)現(xiàn)方式確實(shí)有差別,我們在使用的時(shí)候應(yīng)該根據(jù)場景來判斷選擇哪個(gè)。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • JS實(shí)現(xiàn)為表格動(dòng)態(tài)添加標(biāo)題的方法

    JS實(shí)現(xiàn)為表格動(dòng)態(tài)添加標(biāo)題的方法

    這篇文章主要介紹了JS實(shí)現(xiàn)為表格動(dòng)態(tài)添加標(biāo)題的方法,涉及javascript中createCaption方法添加標(biāo)題的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • js canvas實(shí)現(xiàn)擦除動(dòng)畫

    js canvas實(shí)現(xiàn)擦除動(dòng)畫

    在移動(dòng)設(shè)備上將某張圖片擦掉顯示另一張圖片,利用canvas來實(shí)現(xiàn)這篇文章就為大家詳細(xì)介紹了js canvas實(shí)現(xiàn)擦除動(dòng)畫的相關(guān)資料,感興趣的小伙伴們可以參考一下
    2016-07-07
  • JS調(diào)用某段SQL語句的方法

    JS調(diào)用某段SQL語句的方法

    這篇文章主要為大家詳細(xì)介紹了通過JS調(diào)用某段SQL語句的相關(guān)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • javascript實(shí)現(xiàn)英文首字母大寫

    javascript實(shí)現(xiàn)英文首字母大寫

    本文給大家總結(jié)了幾種可以實(shí)現(xiàn)英文首字母大寫的javascript腳本,另附上一個(gè)CSS的實(shí)現(xiàn)方法,非常的簡單實(shí)用,這里推薦給大家,有需要的小伙伴可以參考下。
    2015-04-04
  • 理解?JavaScript?對象屬性訪問的復(fù)雜性(示例代碼)

    理解?JavaScript?對象屬性訪問的復(fù)雜性(示例代碼)

    在?JavaScript?編程中,開發(fā)者經(jīng)常需要對對象的屬性進(jìn)行訪問,然而,訪問方式的不同可能導(dǎo)致代碼行為的差異,尤其在動(dòng)態(tài)屬性的處理中,本文介紹JavaScript對象屬性訪問的復(fù)雜性,感興趣的朋友跟隨小編一起看看吧
    2024-12-12
  • javascript判斷數(shù)組內(nèi)是否重復(fù)的方法

    javascript判斷數(shù)組內(nèi)是否重復(fù)的方法

    這篇文章主要介紹了javascript判斷數(shù)組內(nèi)是否重復(fù)的方法,涉及javascript針對數(shù)組的相關(guān)操作技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-04-04
  • JavaScript實(shí)現(xiàn)分頁效果

    JavaScript實(shí)現(xiàn)分頁效果

    本文主要介紹了JavaScript實(shí)現(xiàn)分頁效果的示例代碼。具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-03-03
  • 微信小程序如何使用云開發(fā)

    微信小程序如何使用云開發(fā)

    這篇文章主要為大家詳細(xì)介紹了微信小程序如何使用云開發(fā),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • js實(shí)現(xiàn)自定義滾動(dòng)條的示例

    js實(shí)現(xiàn)自定義滾動(dòng)條的示例

    這篇文章主要介紹了js實(shí)現(xiàn)自定義滾動(dòng)條的示例,幫助大家制作JS特效,美化自身網(wǎng)頁,感興趣的朋友可以了解下
    2020-10-10
  • 基于JavaScript制作霓虹燈文字 代碼 特效

    基于JavaScript制作霓虹燈文字 代碼 特效

    這里使用JS實(shí)現(xiàn)網(wǎng)頁上的霓虹燈文字特效代碼特效,運(yùn)行效果看一下,你會(huì)看到文字的顏色像霓虹燈一樣,連續(xù)不停變化,五顏六色的,很炫的樣子,所以就叫做霓虹文字,也可以叫他文字變色效果,下面跟著小編一起學(xué)習(xí)JavaScript制作霓虹燈文字 代碼特效,需要的朋友一起學(xué)習(xí)吧
    2015-09-09

最新評論

巴彦县| 边坝县| 建湖县| 长治县| 济源市| 隆尧县| 临邑县| 满洲里市| 增城市| 舒兰市| 安仁县| 南丰县| 浮梁县| 钟祥市| 介休市| 铁岭市| 锦州市| 同江市| 常州市| 和林格尔县| 怀安县| 河曲县| 和平区| 都兰县| 镇原县| 天门市| 讷河市| 永泰县| 夏河县| 祁东县| 交城县| 汉源县| 栾川县| 碌曲县| 绥芬河市| 右玉县| 平顺县| 巩留县| 武宁县| 延津县| 保山市|