前端時空前端
前端網紅集結號,傳遞一線全棧技術,帶你穿越前端時空。編程
發佈訂閱模式,由觀察者模式衍化而來,定義了對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都將獲得通知,並自動更新。與發佈訂閱模式不一樣的是,觀察者模式的區別在於訂閱者與發佈者具備直接依賴關係,而發佈訂閱模式由一箇中間人進行消息的統一調度。咱們先從觀察者模式開始。bash
引一個生動的小例子,王和小李知道張三是賣報的夥計,他們都想在張三那裏買報紙。小王和小李便和張三約定,一旦張三有了新報紙,就通知他倆。這裏,小王和小李做爲觀察者,張三做爲被觀察者,張三和王、李創建起一對多的通信關係。此時一旦有消息發佈,依賴於被觀察者的對象都將獲得通知,並自動更新。框架
下面 p一、p二、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元的報紙。王、李根據自身狀況當即作出響應。函數
發佈訂閱模式的不一樣在於,觀察者訂閱者和訂閱目標是聯繫在一塊兒的,也就是王、李、張都是熟人,互相有聯繫。ui
而在發佈訂閱模式中,稱爲發佈者的消息發送者不會將消息直接發送給訂閱者,這意味着發佈者和訂閱者不知道彼此的存在。在發佈者和訂閱者之間存在第三個組件,稱爲消息代理或調度中心或中間件,它維持着發佈者和訂閱者之間的聯繫,過濾全部發布者傳入的消息並相應地分發它們給訂閱者。this
也就是說,如今的小王、小李,開始在報社訂閱報紙了,張三也把本身的報紙賣到報社,由報社進行銷售。這個報社,就是調度中心。訂閱和發佈事件,由這個調度中心統一管理。spa
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 自動觸發來發布報紙。prototype
JavaScript 發佈訂閱模式得益於函數式編程中的高階函數概念,它具備十分普遍的應用。JavaScript Vue 框架的就採用了這種設計理念。Vue 框架利用 Object.defineProperty + 發佈訂閱模式實現了雙向綁定。Observer、Dep、Watcher 就充當了發佈者、topic、訂閱者。感興趣的小夥伴,能夠繼續關注咱們喲。