JS每日一題:設計模式-如何理解觀察者(發佈訂閱)模式?

20190411期

設計模式-如何理解觀察者(發佈訂閱)模式?設計模式

定義: 觀察者模式又叫發佈訂閱模式(Publish/Subscribe),它定義了一種一對多的關係,讓多個觀察者對象同時監聽某一個主題對象,這個主題對象的狀態發生變化時就會通知全部的觀察者對象,使得它們可以自動更新本身

生活實例理解:你今天去看一個樓盤,去了以後發佈樓盤尚未對外銷售,你不知道樓盤時候會對外銷售,因而你找了樓盤的負責人,告訴他何時樓盤開始銷售了電話通知你,而後想要買的人不是你一個,其它人也是經過留電話的方式給銷售負責人來及時獲取消息緩存

不難發現,上面的例子正好對應上咱們的觀察者模式的定義, 多個想要買房的人同時訂閱了一個主題(樓盤對外銷售),這個主題更新時,這些觀察者(買房)都會做出相應的動做app

最熟悉的代碼理解:學習

實際上,咱們常常用到的事件綁定就是發佈訂閱模式this

在這裏咱們想在用戶點擊的時候作出相應的處理,可是咱們不知道用戶在何時去點擊,因此咱們去訂閱body上的click事件,在這裏咱們還能夠去隨意增長訂閱者,這樣並不影響咱們的發佈者prototype

document.body.addEventListener('click',function(){
  console.log('JS 每日一題')
},false)

document.body.addEventListener('click',function(){
  console.log('今天你打卡了嗎?')
},false)
實現一個簡版的觀察者

首先咱們順一下思路設計

  • 誰是發佈者
  • 誰是訂閱者
  • 發生改變時怎麼通知訂閱者做出相應動做
const Boss = {} //樓盤銷售負責人
Boss.clientList = []; // 存放訂閱者的回調
Boss.listen = function(fn){ // 增長訂閱者
    this.clientList.push(fn); // 將買房人的號碼緩存起來
}
Boss.trigger = function(){ // 發佈消息
    for(var i=0,fn; fn= this.clientList[i++];){
      fn.apply(this,arguments)
    }
}

Boss.listen(function(msg){
  console.log(msg) // 開始銷售了
})

cdBoss.trigger('開始銷售了') // 發佈消息

咱們已經實如今最簡易版的發佈訂閱,但實際上是存在問題的,每一個人可能訂閱戶型是不一樣的, 上面咱們實現的是,只要一開始銷售就通知全部訂閱的人,顯然是不合理的,咱們將代碼再來改寫一下code

// 訂閱時給其加一個key作爲標識,就至關於key就是訂閱者的身份
Boss.listen = function(key, fn){
    if (!this.clientList[key]) {
      // 若是沒有此類訂閱,就給該類訂閱增長一個緩存列表 
      this.clientList[key] = []
    }
    this.clientList[key].push(fn); 
}

Boss.trigger = function(){ // 發佈消息
    const key = Array.prototype.shift.call(arguments),
    // 取出消息類型
    fns = this.clientList[key] 
    if (!fns || !fns.length) return // 若是該類消息沒有訂閱直接返回
    for (var i = 0, fn; fn = fns[i++]) {
        fn.apply(this, arguments)
    }
}

Boss.listen('老王', function (msg) {
  console.log('老王訂閱戶型' + cdName)
}) 
Boss.listen('老李', function (cdName) {
  console.log('老李訂閱戶型' + cdName)
}) 
Boss.trigger('老王', '143平米');
Boss.trigger('老李', '888平米');

好了,通過改寫,消息只會推送給相關的訂閱者了cdn

總結

  • 時間上的解藕
  • 對象之間的解藕

總的來講,觀察者模式所作的工做就是在解耦,讓耦合的雙方都依賴於抽象,而不是依賴於具體。從而使得各自的變化都不會影響到另外一邊的變化對象

關於JS每日一題

JS每日一題能夠當作是一個語音答題社區
天天利用碎片時間採用60秒內的語音形式來完成當天的考題
羣主在第二天0點推送當天的參考答案

  • 注 毫不僅限於完成當天任務,更可能是查漏補缺,學習羣內其它同窗優秀的答題思路

點擊加入答題

相關文章
相關標籤/搜索