一、發布訂閱者模式js
發布訂閱者模式又稱為觀察者模式,是一種常見的軟件設計模式,屬於行為型模式。該模式定義了一種一對多的關係,讓多個觀察者對象同時監聽某一個主題對象,當一個對象發生改變時,所有依賴於它的對象都將得到通知並被自動更新。
在JavaScript中,我們可以使用事件機制來實現發布訂閱者模式。事件機制本質上就是一種發布訂閱者模式的實現。我們可以通過事件機制來為一個事件註冊回調函數,當這個事件觸發時,所有註冊的回調函數都會被依次調用。
class EventEmitter { constructor() { this._events = {} } on(event, callback) { if (!this._events[event]) { this._events[event] = [] } this._events[event].push(callback) } emit(event, ...args) { if (!this._events[event]) { return } this._events[event].forEach(fn => { fn.apply(this, args) }) } }
二、發布訂閱者模式和觀察者模式代碼
發布訂閱者模式和觀察者模式在概念上很相似,都是建立了一種一對多的依賴關係。但是它們的實現方式有所不同。在觀察者模式中,觀察者對象需要直接訂閱主題對象,而在發布訂閱者模式中,發布者和訂閱者之間則沒有直接的聯繫,而是通過發布-訂閱通道來進行通信。
下面是觀察者模式和發布訂閱者模式的示例代碼:
//觀察者模式 class Subject { constructor() { this.observers = [] } addObserver(observer) { this.observers.push(observer) } removeObserver(observer) { const index = this.observers.indexOf(observer) if (index !== -1) { this.observers.splice(index, 1) } } notify() { this.observers.forEach(observer => observer.update()) } } class Observer { constructor(name, subject) { this.name = name this.subject = subject this.subject.addObserver(this) } update() { console.log(`${this.name} has been notified`) } } const subject = new Subject() const observer1 = new Observer('observer1', subject) const observer2 = new Observer('observer2', subject) subject.notify() // 'observer1 has been notified', 'observer2 has been notified' //發布訂閱者模式 class EventBus { constructor() { this.subscribers = {} } subscribe(event, callback) { if (!this.subscribers[event]) { this.subscribers[event] = [] } this.subscribers[event].push(callback) } unsubscribe(event, callback) { if (!this.subscribers[event]) { return } const index = this.subscribers[event].indexOf(callback) if (index !== -1) { this.subscribers[event].splice(index, 1) } } publish(event, ...args) { if (!this.subscribers[event]) { return } this.subscribers[event].forEach(fn => { fn.apply(this, args) }) } } const eventBus = new EventBus() const callback1 = () => console.log('callback1 is called') const callback2 = () => console.log('callback2 is called') eventBus.subscribe('test', callback1) eventBus.subscribe('test', callback2) eventBus.publish('test') // callback1 is called', 'callback2 is called' eventBus.unsubscribe('test', callback1) eventBus.publish('test') // 'callback2 is called'
三、發布訂閱者模式實例代碼
下面是一個發布訂閱者模式的實例,我們模擬了一個購買商品的場景。當用戶購買商品時,我們將觸發一個名為“buy”事件,並傳遞商品名稱和價格。購物車和訂單模塊可以訂閱該事件,以便在用戶購買商品時更新購物車和訂單信息。
class EventBus { constructor() { this.subscribers = {} } subscribe(event, callback) { if (!this.subscribers[event]) { this.subscribers[event] = [] } this.subscribers[event].push(callback) } unsubscribe(event, callback) { if (!this.subscribers[event]) { return } const index = this.subscribers[event].indexOf(callback) if (index !== -1) { this.subscribers[event].splice(index, 1) } } publish(event, ...args) { if (!this.subscribers[event]) { return } this.subscribers[event].forEach(fn => { fn.apply(this, args) }) } } const eventBus = new EventBus() class Cart { constructor() { this.items = [] eventBus.subscribe('buy', this.add.bind(this)) } add(item) { this.items.push(item) console.log(`Item ${item.name} is added to the cart`) } } class Order { constructor() { this.items = [] eventBus.subscribe('buy', this.add.bind(this)) } add(item) { this.items.push(item) console.log(`Item ${item.name} is added to the order`) } } const cart = new Cart() const order = new Order() eventBus.publish('buy', { name: 'iPhone', price: '999' }) // 'Item iPhone is added to the cart', 'Item iPhone is added to the order'
四、發布訂閱者模式怎麼理解
發布訂閱者模式是一種解耦的方式,將生產者和消費者完全解耦,使得它們之間沒有直接的依賴關係。生產者和消費者之間僅僅通過一個中間件來通信。生產者將消息發布到中間件中,而消費者則從中間件中訂閱消息。這種解耦方式使得系統變得更加鬆散,更容易擴展和維護。
發布者訂閱者模式可以應用於很多地方,比如事件機制、消息隊列、Redux等。在Vue.js中,也使用了類似的機制來實現組件間的通信,將組件間的通信從父子關係中解耦出來,使得組件之間具有更高的可擴展性和復用性。
五、發布訂閱者模式面試題
以下是一些與發布訂閱者模式相關的面試題:
1、請說出發布訂閱者模式和觀察者模式的區別。
答:在發布訂閱者模式中,發布者和訂閱者之間沒有直接的聯繫,而是通過一個中間件來進行通信。而在觀察者模式中,觀察者對象需要直接訂閱主題對象。
2、請說出事件機制的實現方式。
答:事件機制本質上就是一種發布訂閱者模式的實現。我們可以為一個事件註冊回調函數,當這個事件觸發時,所有註冊的回調函數都會被依次調用。
六、發布訂閱者模式的實現
下面是一個基於ES6的發布訂閱者模式的實現:
class EventBus { constructor() { this.subscribers = new Map() } subscribe(event, callback) { if (!this.subscribers.has(event)) { this.subscribers.set(event, []) } this.subscribers.get(event).push(callback) } unsubscribe(event, callback) { if (!this.subscribers.has(event)) { return } const index = this.subscribers.get(event).indexOf(callback) if (index !== -1) { this.subscribers.get(event).splice(index, 1) } } publish(event, ...args) { if (!this.subscribers.has(event)) { return } this.subscribers.get(event).forEach(fn => { fn.apply(this, args) }) } } const eventBus = new EventBus() eventBus.subscribe('test', () => console.log('test is called')) eventBus.publish('test') // 'test is called' eventBus.unsubscribe('test') // remove all subscribers for 'test' event
七、發布訂閱者模式在Vue中的應用
在Vue.js中,組件間的通信可以通過props傳遞數據、事件派發和監聽等方式來實現。其中事件派發和監聽的機制就是基於發布訂閱者模式來實現的。當組件A需要向組件B發送事件時,它會使用$emit方法來觸發一個名為event的事件,並傳遞參數值。而組件B則需要使用$on方法來註冊這個事件,並在回調函數中處理參數值。
以下是一個在Vue中使用發布訂閱者模式來進行組件通信的實例:
//Parent.vue <template> <Child @eventName="handleEvent"></Child> </template> <script> import { EventBus } from '@/event-bus.js' export default { methods: { handleEvent() { // handle event here } }, mounted() { EventBus.$on('eventName', this.handleEvent) }, beforeDestroy() { EventBus.$off('eventName', this.handleEvent) } } </script> //Child.vue <template> <button @click="sendEvent">Send Event</button> </template> <script> import { EventBus } from '@/event-bus.js' export default { methods: { sendEvent() { EventBus.$emit('eventName', data) } } } </script> //event-bus.js import Vue from 'vue' export const EventBus = new Vue()
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/235925.html