設計模式-釋出訂閱
阿新 • • 發佈:2020-12-12
技術標籤:web
前言
釋出訂閱又叫觀察者模式,它記錄的是一種一對多的依賴關係,當訂閱的資料狀態發生改變時,所對應的依賴的物件會得到訊息(通知)。
優點
釋出訂閱在非同步程式設計中,可以替代回撥,從而無需關注物件在非同步執行中的內部狀態,只需要關注有用的事件發生點。物件之間的解耦。
釋出-訂閱的組成要素
一個釋出訂閱包包含了三要素,釋出者(Publisher),訂閱者(Subscriber),排程處理中心(Event channel)。
當Publisher釋出一個事件到Event channel,Subscriber就會收到由Event Bus觸發的事件的通知。
釋出訂閱的簡單實現
class EventEmeitter {
constructor(){
this.events = new Map();
this._maxListeners = this._maxListenners || 10;
}
// 釋出
emit(type,...args){
let handler;
handler = this.events.get(type);
if(Array.isArray(handler)){
for(let i = 0; i < handler.length; i++){
if(args.length>0){
handler[i].apply(this,args);
}else{
handler[i].apply(this);
}
}
}else{
if(args.length>0){
handler. apply(this,args);
}else{
handler.apply(this);
}
}
return true;
}
// 新增監聽事件
addEventListener(type,fn){
const handler = this.events.get(type); // 獲取對應事件名稱的函式
if(!handler){
this.events.set(type,fn);
}else if(handler && typeof handler === 'function'){
// 如果handler是函式說明當前只有一個監聽函式
this.events.set(type,[handler,fn]);
}else{
if(handler.length <= this._maxListenners) return handler.push(fn); // 新增多個監聽有上限
}
}
// 移除監聽事件
removeListener(type, fn){
const handler = this.events.get(type); // 獲取對應事件名稱的函式
// 如果是函式,說明只被監聽了一次
if(handler && typeof handler === 'function'){
this.events.delete(type,fn);
}else{
// 如果handler是陣列,說明被多次監聽,需要找到對應的函式的位置
let position;
for(let i = 0 ; i< handler.length; i++){
if(handler[i] === fn){
position = i
}else{
position = -1;
}
}
// 如果找到匹配的函式
if(position !== -1){
// 直接刪除
handler.splice(position,1);
// 如果清除後只有一個函式,那麼取消陣列,以函式形式儲存
if(handler.length ===1){
this.events.set(type,handler[0]);
}
} else {
return this;
}
}
}
}
例子
釋出訂閱的應用場景
比如我們很喜歡看某個公眾號號的文章,但是我們不知道什麼時候釋出新文章,要不定時的去翻閱;這時候,我們可以關注該公眾號,當有文章推送時,會有訊息及時通知我們文章更新了。
看似簡單的操作,其實是一個典型的釋出訂閱模式,公眾號屬於釋出者,使用者屬於訂閱者;使用者將訂閱公眾號的事件註冊到排程中心,公眾號作為釋出者,當有新文章釋出時,公眾號釋出該事件到排程中心,排程中心會及時發訊息告知使用者。
基於公眾號的釋出訂閱
// 例項化event bus
const eventBus = new EventEmeitter()
//訂閱方法
function user1(data){
console.log(`訂閱使用者1`, data)
}
function user2(data){
console.log(`訂閱使用者2`, data)
}
// 新增訂閱
eventBus.addEventListener('article', user1)
eventBus.addEventListener('article', user2)
// 釋出
eventBus.emit('article', '有新的文章釋出了')
歡迎訪問主頁,有更多文章內容
轉載請註明原出處
原文連結地址:設計模式-釋出訂閱