发布订阅模式与简单的 JS 实现
发布订阅模式与简单的 JS 实现
本文写于 2020 年 9 月 22 日
观察者模式(Observer Pattern)是一种设计模式,也可以叫做「发布-订阅模式」。
等等,其实我也不清楚,通常你在网上会看到上面这一段话,但我在 Angular 文档中读到谷歌的说法是这样的:观察者模式和发布/订阅模式非常相似(但不完全一样)。
好吧,我们姑且就直说发布订阅模式吧。
发布订阅模式就像你订了一本杂志,每当杂志新刊发布的时候,所有订阅过杂志的人都会收到新刊一样。
观察者模式定义了对象之间一种 一对多 的依赖关系,每当该对象的状态发生改变的时候,所依赖于它的其他对象都将得到通知。
在 JavaScript 中,我们会经常接触到一个很类似的东西——事件。
事件与观察者模式
我们先为一个 #app 元素添加两个点击事件:
document.querySelector('#app').addEventListener('click', () => { // 事件 1 }); document.querySelector('#app').addEventListener('click', () => { // 事件 2 });
这个时候,我们点击 #app 元素或者使用 document.querySelector('#app').click()
或者 document.querySelector('#app').dispatchEvent('click')
来触发时,这两个事件都会被触发——是不是类似与很多对象依赖于一个对象,该对象改变后所有依赖者都会被触发。
自定义「发布-订阅」
我们来自定义一个事件来试试。
首先我们需要一个数组储存所有的触发函数,这样我们就可以对其进行遍历,后触发每一个事件。
const children = [];
我们还需要一个方法,来对 children 数组进行 push
。
const listen = (fn) => { children.push(fn); }
我们再增加一个触发函数 trigger
,让它去遍历并触发我们的 children
const trigger = () => { children.forEach((child) => { child(); }) }
OK,接下来我们整合一下:
class eventHub { children = {} listen(key, fn) { if(this.children[key]) { this.children[key].push(fn); } else { this.children[key] = [fn] } } trigger(key) { this.children[key]?.forEach((child) => { child(); }); } remove(key, fn) { if(this.children[key]) { const children =this.children[key] const target = children.indexOf(fn) this.children[key] = [...children.slice(0, target), ...children.slice(target + 1)] } } }
这里我们将数组换成了对象,并且为函数增加了参数,因为我们希望够可以对多个事件进行监听。
还添加了一个移除事件——所以我们最好使用具名函数,如果是匿名函数就无法移除监听了!
有哪些例子?
例如一个电商网站的登陆系统,需要获取用户基础信息后,获取用户的各项历史记录:
function onLogin() { getUserInfo() .then(() => { return getUserHistory() }) .then(() => { getUserXXX() }) }
那么一旦我们需要新增一个功能,就需要在这个长函数中增加新项。
如果使用了发布-订阅模式,就可以非常简单的写上新的、独立的事件监听了。
(完)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 从 Windows Forms 到微服务的经验教训
· 李飞飞的50美金比肩DeepSeek把CEO忽悠瘸了,倒霉的却是程序员
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee