前端時空
前端網紅集結號,傳遞一線全棧技術,帶你穿越前端時空。
釋出訂閱模式,由觀察者模式衍化而來,定義了物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都將得到通知,並自動更新。與釋出訂閱模式不同的是,觀察者模式的區別在於訂閱者與釋出者具有直接依賴關係,而釋出訂閱模式由一箇中間人進行訊息的統一排程。我們先從觀察者模式開始。
觀察者模式
引一個生動的小例子,王和小李知道張三是賣報的夥計,他們都想在張三那裡買報紙。小王和小李便和張三約定,一旦張三有了新報紙,就通知他倆。這裡,小王和小李作為觀察者,張三作為被觀察者,張三和王、李建立起一對多的通訊關係。此時一旦有訊息釋出,依賴於被觀察者的物件都將得到通知,並自動更新。
下面 p1、p2、p3 分別代表王、李、張三。
function Person(name) {
this.name = name;
this.list = []
}
Person.prototype.publish = function (money){
console.log(this.name + '賣報一份'+money+"元")
this.list.forEach(function(item, index){
item(money)
})
}
Person.prototype.subscribe = function (targrt,fn){
console.log(this.name + '準備買' + targrt.name+'的報紙');
targrt.list.push(fn)
}
let p1 = new Person('p1')
let p2 = new Person('p2')
let p3 = new Person('p3')
p1.subscribe(p3 ,(money)=>{
console.log(money >= 100 ? '太貴了,不買' : '買一份');
})
p2.subscribe(p3 ,(money)=>{
console.log(money >= 200 ? '太貴了,不買' : '買一份');
})
p3.publish(120)複製程式碼
張三釋出了120元的報紙。王、李根據自身情況立即做出響應。
釋出訂閱模式
釋出訂閱模式的不同在於,觀察者訂閱者和訂閱目標是聯絡在一起的,也就是王、李、張都是熟人,互相有聯絡。
而在釋出訂閱模式中,稱為釋出者的訊息傳送者不會將訊息直接傳送給訂閱者,這意味著釋出者和訂閱者不知道彼此的存在。在釋出者和訂閱者之間存在第三個元件,稱為訊息代理或排程中心或中介軟體,它維持著釋出者和訂閱者之間的聯絡,過濾所有釋出者傳入的訊息並相應地分發它們給訂閱者。
也就是說,現在的小王、小李,開始在報社訂閱報紙了,張三也把自己的報紙賣到報社,由報社進行銷售。這個報社,就是排程中心。訂閱和釋出事件,由這個排程中心統一管理。
let Topic = {
topics: {},
subscribe(topic, fn) {
if (!this.topics[topic]) {
this.topics[topic] = []
}
this.topics[topic].push(fn)
},
publish(topic, money) {
if (this.topics[topic]) {
for (let fn of this.topics[topic]) {
fn(money)
}
}
}
}
function Person(name) {
this.name = name
}
Person.prototype.subscribe = function (topic, fn) {
console.log('訂閱者' + this.name + '訂閱了' + topic )
Topic.subscribe(topic, fn)
}
Person.prototype.publish = function (topic, money) {
console.log('釋出者' + this.name + '釋出了' + topic )
Topic.publish(topic, money)
}
let p1 = new Person('p1')
let p2 = new Person('p2')
let p3 = new Person('p3')
p1.subscribe('北京日報',(money)=>{
console.log(money >= 100 ? '太貴了,不買' : '訂閱');
})
p2.subscribe('上海日報',(money)=>{
console.log(money >= 200 ? '太貴了,不買' : '訂閱');
})
p2.subscribe('北京日報',(money)=>{
console.log('訂閱');
})
p3.publish('北京日報', 198)複製程式碼
此時,三位訂閱者通過 topic 訂閱報紙,報社通過 topic 自動觸發來發布報紙。
尾聲
JavaScript 釋出訂閱模式得益於函數語言程式設計中的高階函式概念,它具有十分廣泛的應用。JavaScript Vue 框架的就採用了這種設計理念。Vue 框架利用 Object.defineProperty + 釋出訂閱模式實現了雙向繫結。Observer、Dep、Watcher 就充當了釋出者、topic、訂閱者。感興趣的小夥伴,可以繼續關注我們喲。