設計模式-如何理解觀察者(發佈訂閱)模式?設計模式
定義: 觀察者模式又叫發佈訂閱模式(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每日一題能夠當作是一個語音答題社區
天天利用碎片時間採用60秒內的語音形式來完成當天的考題
羣主在第二天0點推送當天的參考答案