JavaScript發佈訂閱者模式

假如你要創建一個網站,一般來講會有許多用戶。你做爲一名管理者,有時候須要將重要的消息發佈給你的用戶。在軟件開發領域,開發此功能每每用到發佈訂閱者模式。下面我以簡單的javascript來講明。javascript

  1. 定義發佈者類。發佈者最基本的兩個屬性:發送的消息,發送的人
function Publisher() {
  this.observers =[]; // 存儲須要發佈消息的人
  this.state="hello"  // 發送的消息
}
複製代碼

除此以外,一個Publisher還須要有可以接納新的訂閱消息的人的功能,或者刪除某個訂閱者的功能,同時須要可以將消息發送出去的功能。java

// 新增訂閱者功能
Publisher.prototype.addUser=function(obj) {
  const nameList= this.observers.map(item=>{
    return item.name;
  })
  if(nameList.indexOf(obj.name) < 0) {
    this.observers.push(obj)
  }
  return this;
}
//刪除訂閱者功能
Publisher.prototype.deleteUser=function(obj){
  let index = -1
  this.observers.forEach((item,key)=>{
    if(item.name === obj.name){
      index = key
    }
  })
  if(index !== -1) {
    this.observers.splice(index,1)
  }
  return this
}
// 通知訂閱者功能
Publisher.prototype.noticeUser=function(data){ 
  this.observers.forEach((item)=>{
    item.update(data)
  })
}
複製代碼

值得注意的是,上述通知訂閱者的功能是經過遍歷this.observers 並調用每個訂閱者的update方法。因此每個訂閱者須要對應有update方法。每個訂閱者的相似結構以下:bash

[
  {
    name:'張三',
    update:(data)=>{console.log(data)}
  },
  {
    name:'李四',
    update:(data)=>{console.log(data)}
  },
  ...
]
複製代碼
  1. 構造訂閱者對象,因爲每個訂閱者都有name屬性和update方法。最簡單的就是採用構造函數方法來實現
function Subscribe(name){
  this.name =name;
  this.update = function(data){
    console.log(data);
  };
}
複製代碼
  1. 有了Subscribe模板,咱們開始構造出每個具體的訂閱者實例出來。
let lisi = new Subscribe('lisi')
let xiaoming = new Subscribe('xiaoming')
複製代碼
  1. 將構造的訂閱人lisi 和 xiaoming 加入到發佈者對象的observer中
let pb = new Publisher()
pb.addUser(lisi)
pb.addUser(xiaoming)
複製代碼
  1. 發佈者須要發佈消息時:
pb.noticeUser("hello")
複製代碼

至此一個最簡單的發佈訂閱者模式實現了,這裏還有兩點優化建議。
第一,上述構造出來的lisi,xiaoming都會自動有update方法,而且update的行爲都是同樣的,若是須要例如xiaoming的update與其餘不一樣,只須要從新定義便可函數

xiaoling.update=(data)=>{console.log("hello"+data)}
pb.addUser(xiaoling)
複製代碼

第二, 發佈者須要手動調用pb.noticeUser()去通知state消息,能夠作到state變更了自動去調用pb.noticeUser()嗎?能夠的,此時 Object.defineProperty()就派上用場了優化

let pb = new Publisher()
Object.defineProperty(pb,'state',{
  set:function(newVal,) {
    let a = this
    debugger
    pb.noticeUser(newVal)   
  }
})
pb.addUser(lisi)
pb.addUser(xiaoming)
pb.state = '123'
//pb.noticeUser()
複製代碼

若是state變化了將自動觸發pb.noticeUser(),實現自動通知功能,是否是有點Vue原理既視感!網站

相關文章
相關標籤/搜索