设计模式之观察者模式
1. 定义
当一个对象被修改时,则会自动通知依赖它的对象
2. 口语化表述
观察者模式或许听起来不是很耳熟,但是说起订阅模式,大部分人就能理解
比如,微信公众号里,你订阅的公众号如果发了新消息,微信就会通知你,你在你的微信里就能看到(没订阅自然不会收到)
其实这就是观察者模式(事件订阅者模式),多个对象观察(监听)某一对象,当这个对象发生变化时,观察的对象就会知道并作出变化
(下面的描述会沿用这个上述这个场景)
3. 源码示例
观察者模式在前端可是处处都能看到,比如浏览器事件机制
HTML页面里的元素很多都有内置的事件,比如Button具有监听点击事件
假设设置了点击事件的触发函数(onClick),当你点击了Button时,Button就会接收到这个事件并执行之前设置的触发函数(onClick)
这里看上去,是一对一的关系,就是一个点击事件触发一次函数,有没有一对多的呢?答案是有,比如,全局事件总线
全局事件总线,就是让事件系统置于全局,在系统的任意地方都能触发事件,在系统任意地方都能接收事件消息并执行对应函数
原理很简单,一个全局对象,实现发布事件的接口,实现订阅事件的接口,实现存储事件及对应触发函数,就是一个全局事件总线
Vue2 就实现了类似的接口,所以可以当作一个全局事件总线使用(Vue3 做了修改,无法再把Vue当作一个事件总线来使用)
Vue2 中的 Vue 原型对象上包含事件处理的方法:
- $on(eventName, listener): 绑定自定义事件监听
- $emit(eventName, data): 分发自定义事件
- $off(eventName): 解绑自定义事件监听
- $once(eventName, listener): 绑定事件监听, 但只能处理一次
所以,只要设置一个全局Vue对象,然后就可以在任意组件里绑定事件监听并设置更新函数,在任意组件里分发(触发)这个事件,这就实现了全局事件总线
全局事件总线就是观察者模式的典型应用,即一处修改,则会自动通知监听这处的其他地方并执行对应的函数
4. 总结
4.1 设计优点
-
开闭原则
在上述微信公众号示例中,新的用户加入与新的公众号加入,都无需修改现有的系统
4.2 适用场景
-
一个对象状态的改变需要改变其他对象
某个微信公众号修改了,需要自动通知订阅它的用户
-
一些对象必须观察其他对象时
浏览器事件机制里,必须触发对应的事件才能执行对应的函数