大家好,我是前端老司机,今天要聊的是设计模式中的「微信公众号」——发布订阅模式。这不是什么高大上的技术,而是让代码更灵活、更解耦的实用技巧。
发布订阅模式是个啥?
简单来说,发布订阅模式就是:一个主题对象状态改变时,能通知所有订阅了它的观察者对象。就像微信公众号一样,博主发文章(发布事件),所有关注的粉丝(订阅者)都会收到推送(执行相应操作)。
最重要的一点是:发布者不直接接触订阅者,而是通过一个第三方(事件中心)来通信。这就像公众号平台一样,博主和粉丝之间没有直接联系,但通过平台可以实现信息的传递。
从代码看发布订阅模式的实现
让我们来看一个典型的发布订阅模式实现:
class EventEmitter {
constructor() {
this.eventList = {
// 'hasHouse': [kang, wrap],
// 'hasCar': [cheng]
}
}
on(eventName, cb) { // 订阅
if (!this.eventList[eventName]) {
this.eventList[eventName] = []
}
this.eventList[eventName].push(cb)
}
emit(eventName) { // 发布
if (this.eventList[eventName]) {
const handlers = this.eventList[eventName].slice()
handlers.forEach((item) => {
item()
})
}
}
off(eventName, cb) { // 取消订阅
const callbacks = this.eventList[eventName]
const index = callbacks.indexOf(cb)
if (index !== -1) {
callbacks.splice(index, 1)
}
}
once(eventName, cb) { // 订阅一次
const wrap = () => {
cb()
this.off(eventName, wrap)
}
this.on(eventName, wrap)
}
}
这个 EventEmitter 类就是我们的「公众号平台」,它提供了四个核心方法:
on: 订阅事件(关注公众号)emit: 发布事件(推送文章)off: 取消订阅(取消关注)once: 订阅一次事件(一次性推送)
发布订阅模式的「实战演练」
让我们用一个生活中的例子来演示如何使用发布订阅模式:
// 创建事件中心(公众号平台)
let _event = new EventEmitter()
// 定义订阅者(粉丝)
function kang() { // 康总
console.log('康总买房')
}
function ji() { // 老骥
console.log('老骥买房');
}
function cheng() { // 成哥
console.log('成哥买车位');
}
// 订阅事件(关注公众号)
_event.on('hasHouse', kang) // 康总关注了「有房了」公众号
_event.once('hasHouse', ji) // 老骥只关注一次「有房了」公众号
_event.on('hasCar', cheng) // 成哥关注了「有车了」公众号
// 发布事件(推送文章)
_event.emit('hasHouse') // 「有房了」公众号推送了文章
// 输出:
// 康总买房
// 老骥买房
_event.emit('hasHouse') // 「有房了」公众号再次推送文章
// 输出:
// 康总买房
// (老骥因为只订阅一次,所以第二次没收到)
这个例子完美诠释了发布订阅模式的工作原理:当某个事件(有房了)发生时,所有订阅了这个事件的函数都会被调用。而且,通过 once 方法,我们还实现了只订阅一次的功能。
发布订阅 vs 观察者:傻傻分不清?
很多人会把发布订阅模式和观察者模式搞混,其实它们有一个关键区别:
- 发布订阅模式:发布者和订阅者之间有一个第三方(事件中心),它们不直接接触
- 观察者模式:发布者(被观察者)直接接触订阅者(观察者)
就像:
- 发布订阅模式 = 微信公众号(平台)+ 博主 + 粉丝
- 观察者模式 = 直销员 + 客户(直销员直接联系客户)
发布订阅模式的「高光时刻」
发布订阅模式在前端开发中简直是「香饽饽」,它的应用场景无处不在:
- DOM 事件监听:
document.addEventListener('click', handler)就是典型的发布订阅模式 - Vue/React 等框架的事件系统:组件间通信经常用到发布订阅模式
- Redux/Vuex 等状态管理库:状态变化时通知组件更新
- Node.js 的 EventEmitter:Node.js 核心模块,广泛用于各种事件处理
写在最后
发布订阅模式就像 JavaScript 世界里的「微信公众号」,它让代码之间的通信变得更加灵活、解耦。通过一个第三方的事件中心,发布者和订阅者可以互不相识,但依然能够完美协作。
下次写代码时,如果你发现多个组件或模块之间需要通信,但又不想让它们直接耦合,不妨试试发布订阅模式,让你的代码像微信公众号一样高效运作!
你在项目中用过发布订阅模式吗?欢迎在评论区分享你的使用经验~