发布订阅模式
在软件架构中,发布-订阅是一种消息范式,消息的发布者不会将消息直接发送给特定的订阅者。而是将发布的消> 息分为不同的类别来管理,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多 个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。 ----引自 wiki
发布订阅设计模式在程序中经常涉及,例如 Vue 中的 $on 和 $off、document.addEventListener()、document.removeEventListener()等,发布订阅模式可以降低程序的耦合度,统一管理维护消息、处理事件也使得程序更容易维护和扩展
发布者和订阅者需要通过发布订阅中心进行关联,发布者的发布动作和订阅者的订阅动作相互独立,无需关注对方,消息派发由发布订阅中心负责
与观察者模式的区别
● 在观察者模式中,观察者是知 道 Subject 的,Subject 一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。 ● 在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。 ● 观察者模式大多数时候是同步的,比如当事件触发,Subject 就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列) ● 在观察者模式中,没有发布者和订阅者的概念,只有主体(Subject)和观察者(Observer)的概念。所有观察者的信息,都需要依靠主体自己去维护,当某个事件发生的时候,主体需要挨个地去通知观察者。 ● 相比于观察者模式,发布订阅模式中的发布者和订阅者之间增加了一层 Event Channel(也叫 EventEmitter/EventBus),用于维护所有的订阅者,这就保证了发布者和订阅者二者是松耦合的。
变体
- push v.s. pull ● push 在事件发生时,发布者一次性把所有更改的状态和数据都推送给订阅者 ● pull 发布者仅仅通知订阅者事件已经发生,并提供一些公开的接口让订阅者来主动拉取数据 由于 arguments 的存在,使用 push 模型可以方便地将所有参数都提供给订阅者。
仅接收一次 once 存在一些场景,可能某些消息是不会持续更新的,或者订阅者只期望接收一次消息,那么发布者也只需要发布一次,后续即使再发布,订阅者也不再关注。 为满足这个场景,就需要提供 once 方法,在订阅的方法中,直接完成退订操作: