JavaScript中的设计模式:发布-订阅模式
字数 588 2025-11-05 23:47:39
JavaScript中的设计模式:发布-订阅模式
发布-订阅模式(Publish-Subscribe Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象。当主题对象状态发生变化时,会通知所有订阅者对象,使它们能够自动更新。
1. 核心概念解析
- 发布者(Publisher):状态变化时负责发布通知的对象
- 订阅者(Subscriber):对特定主题感兴趣并注册监听的对象
- 事件通道(Event Channel):管理订阅关系并传递消息的中间件
2. 基本实现步骤
第一步:创建事件中心(调度中心)
class EventEmitter {
constructor() {
this.events = {}; // 存储事件类型和对应的回调函数数组
}
}
第二步:实现订阅方法(on)
class EventEmitter {
// ... 构造函数
on(eventName, callback) {
// 如果事件不存在,创建一个新数组
if (!this.events[eventName]) {
this.events[eventName] = [];
}
// 将回调函数添加到对应事件的数组中
this.events[eventName].push(callback);
}
}
第三步:实现发布方法(emit)
class EventEmitter {
// ... 之前代码
emit(eventName, ...args) {
// 获取该事件的所有回调函数
const callbacks = this.events[eventName];
if (callbacks) {
// 依次执行所有回调函数
callbacks.forEach(callback => {
callback.apply(null, args);
});
}
}
}
第四步:实现取消订阅方法(off)
class EventEmitter {
// ... 之前代码
off(eventName, callback) {
const callbacks = this.events[eventName];
if (callbacks) {
// 过滤掉要移除的回调函数
this.events[eventName] = callbacks.filter(cb => cb !== callback);
}
}
}
3. 完整基础实现
class EventEmitter {
constructor() {
this.events = {};
}
on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(callback);
}
emit(eventName, ...args) {
const callbacks = this.events[eventName];
if (callbacks) {
callbacks.forEach(callback => callback(...args));
}
}
off(eventName, callback) {
const callbacks = this.events[eventName];
if (callbacks) {
this.events[eventName] = callbacks.filter(cb => cb !== callback);
}
}
once(eventName, callback) {
const wrapper = (...args) => {
callback(...args);
this.off(eventName, wrapper);
};
this.on(eventName, wrapper);
}
}
4. 使用示例
const eventBus = new EventEmitter();
// 订阅事件
eventBus.on('message', (data) => {
console.log('订阅者1收到消息:', data);
});
eventBus.on('message', (data) => {
console.log('订阅者2收到消息:', data);
});
// 发布事件
eventBus.emit('message', 'Hello World!');
// 输出:
// 订阅者1收到消息: Hello World!
// 订阅者2收到消息: Hello World!
// 一次性订阅
eventBus.once('one-time', () => {
console.log('这个只会执行一次');
});
eventBus.emit('one-time'); // 输出:这个只会执行一次
eventBus.emit('one-time'); // 无输出
5. 高级特性扩展
支持命名空间:
class AdvancedEventEmitter extends EventEmitter {
on(namespacedEvent, callback) {
const [eventName, namespace] = namespacedEvent.split('.');
super.on(eventName, callback);
}
emit(namespacedEvent, ...args) {
const [eventName] = namespacedEvent.split('.');
super.emit(eventName, ...args);
}
}
6. 实际应用场景
- DOM事件系统:addEventListener/removeEventListener
- Vue.js的EventBus:组件间通信
- Node.js的EventEmitter模块
- Redux的状态管理
- WebSocket消息推送
7. 模式优势
- 解耦:发布者和订阅者不需要知道对方的存在
- 扩展性:可以方便地添加新的订阅者
- 灵活性:支持一对多的通信关系
这种模式在前端开发中广泛应用,特别是在组件通信、状态管理等场景中发挥着重要作用。