假如你要創建一個網站,一般來講會有許多用戶。你做爲一名管理者,有時候須要將重要的消息發佈給你的用戶。在軟件開發領域,開發此功能每每用到發佈訂閱者模式。下面我以簡單的javascript來講明。javascript
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)}
},
...
]
複製代碼
function Subscribe(name){
this.name =name;
this.update = function(data){
console.log(data);
};
}
複製代碼
let lisi = new Subscribe('lisi')
let xiaoming = new Subscribe('xiaoming')
複製代碼
let pb = new Publisher()
pb.addUser(lisi)
pb.addUser(xiaoming)
複製代碼
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原理既視感!網站