前言
上一章我们介绍了一种简单但是常见的设计模式,迭代器模式,也自己实现了一遍迭代器对象,这一章节要介绍的内容相信大家或多或少都耳濡目染过,那就是发布-订阅模式
正文
发布-订阅模式的定义
发布-订阅模式又称观察者模式,它定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变的时候,所有依赖它的对象都会得到通知。前几章我们介绍的设计模式都分离了业务场景的特殊部分,那么发布-订阅模式呢,没错,就如名字所示的那样,发布-订阅模式分离了发布和订阅的功能,让两者间不再需要互相关注对方内部的逻辑
发布-订阅模式的实现
售楼处的例子
在实现发布-订阅模式前,我们模拟一个场景,假设有一个售楼处,每天会有不同的顾客来订阅楼盘的信息,而售楼的小姐姐会在楼盘的价格信息发生变化的时候,分别通知这些顾客,这就是一个明显的发布-订阅模式的例子。可以发现,这个例子体现了发布-订阅模式的两个明显的优点:
- 顾客不再需要主动一直向售楼小姐姐询问楼盘的消息,也不需要关注什么时候楼盘发生变化,售楼处会去监听,顾客只负责订阅这份消息
- 顾客和售楼处的耦合性降低,当有新的购房者出现的时候,只需要把手机号留在售楼处,而售楼处也并不在意用户的其他信息
实现售楼处的例子
在实现之前,我们先来缕缕这个场景发布-订阅实现的思路,无非就是下面三点:
- 先创建发布者对象(售楼处)
- 给发布者对象创建一个缓存数组,用来存放回调函数来通知不同的订阅者(顾客)
- 当需要发布消息的时候,发布者会遍历这个缓存数组,依次触发里面存放的订阅者回调函数
顺着上面的思路,我们不难封装出下面的售楼处:
这样我们就已经实现好了一个简单的发布-订阅模式,但是上面的实现还并不是完美的,还存在一些问题,并没有对订阅定制化,这样会导致可能你没订阅这个消息也会发布消息,比如小陈只想订阅2号楼盘的价格变化,按上面的写法不管是什么楼盘都会去给小陈发布通知消息,所以我们需要加一个标志的key,让订阅者只收到他们感兴趣的内容
这样就好多了,顾客终于可以订阅自己感兴趣的部分了,售楼处也会根据用户的兴趣去发布对应的消息给顾客!
取消订阅的事件
假设有一天小陈又不感兴趣这个楼盘了,或者已经买好了,但是售楼处还是照常给小陈发短信,小陈想取消掉之前他订阅的事件应该怎么办呢,所以我们为售楼处额外再封装一个remove方法,用于订阅事件的取消
javascript中实现发布-订阅模式的便利性
在java中实现发布-订阅模式,通常会把订阅者本身当作引用传入发布者对象中,同时,订阅者对象还需提供一个名为诸如update的方法,供发布者调用。而在javascript中我们可以直接使用回调函数来代替传统发布-订阅者模式,显得更加优雅
值得一提的是,vue中的双向绑定源码也是使用发布-订阅者模式去实现的,感兴趣的同学可以到网上搜相关源码去阅读
小结
这一章我们给大家介绍了发布-订阅模式,也称观察者模式,发布-订阅模式有着明显的优势:一、减少了程序时间上的耦合;二、减少了各模块间的耦合;可以应用于异步等场景,可以帮助我们编写更加松散耦合的代码
但是发布-订阅模式也有着它的缺陷,创建订阅者会消耗一定的内存,并且当消息一直未发布的时候,订阅者也会一直存在,对内存会有一定的损耗,并且大量的订阅者和发布者交错在一起,也会导致bug的难以追寻踪迹,难以判断其源头,所以也不能滥用发布-订阅模式