读书笔记-JavaScript设计模式与开发实践-发布订阅模式/观察者模式

发布-订阅模式

发布-订阅模式定义了对象间一对多的依赖关系,当一个对象的状态发生改变的时候,所有依赖他的对象都将会得到通知。JS中,用事件模型替代传统的发布-订阅模式。

DOM事件就基于发布订阅模式,比如用户点击body后触发弹窗,我们需要订阅body上的click事件,当按钮被点击的时候,body节点会向订阅者发布这个消息。

document.body.addEventListener('click', function () {
alert('click');
}, false);
document.body.click();

当然上述例子也可以添加删除更多的订阅者,不会影响到发布者内容;

发布-订阅模式小例子

除了DOM事件,我们可以用自定义事件来事件js中的发布订阅模式,实现主要分为几个步骤如下:

  • 1 制订好谁是发布者;
  • 2 给发布者一个缓存列表,用来存储回调函数通知订阅者;
  • 3 发布消息的时候,发布者会遍历缓存列表,触发里面的回调函数通知订阅者;
    还可以在回调函数里加入一些参数,订阅者可以接受参数,进行各自的处理。
    下面的代码为售楼处和购房者的例子,正好应用此模式来实现。
    let salesOffices = {}; // 定义售楼处

    salesOffices.clientList = []; // 缓存列表

    salesOffices.listen = function (fn) { // 添加订阅者
    this.clientList.push(fn); // 订阅的消息进缓存列表
    }

    salesOffices.trigger = function () { // 发布消息
    for (let fn of this.clientList) {
    fn.apply(this, arguments); // argument是发布消息时候的参数
    }
    };

    salesOffices.listen(function (price, squareMeter) { // 小明订阅消息
    console.log('price=' + price);
    console.log('squareMeter=' + squareMeter);
    })

    salesOffices.listen(function (price, squareMeter) { // 小红订阅消息
    console.log('price=' + price);
    console.log('squareMeter=' + squareMeter);
    })

    salesOffices.trigger(200, 88); // 200w,88平
    salesOffices.trigger(300, 188);

上述代码实现了一个最简单的发布-订阅模式,但是存在问题,比如每个订阅者都收到了发布者发布的每个消息,但是小明要是只订阅88平的消息,却收到了全部的,文中后续还增加了标识key,对此进行改进,让订阅者只收到自己感兴趣的消息。

后续还介绍了发布-订阅模式的通用实现和取消订阅的事件,有想要深入了解的可以去书中一探究竟。

例子-网站登陆

这个例子使用发布-订阅模式后的效果深深打动了我,按照自己之前的思路来说,项目开发的规模还是比较小,当登陆成功后,使用ajax一起调用设置头像,消息等等接口,这样登陆后加载内容就有着很强的耦合,每次新增需要在登陆后使用的功能模块,都要在登陆成功后加载的函数中调用,去更改函数。但是使用发布-订阅模式后对登陆信息感兴趣的模块可以自行订阅登陆成功的消息事件,这样登陆模块就不需要管业务方做什么了,登陆成功后发布登陆成功消息就可以了,这样新增功能模块也不用再更改登陆成功后的函数。

总结

除了文中上面描述的,书中本章还介绍了全局的发布订阅对象、如何封装进行模块间通信、还有使用全局事件命名冲突的处理(创建命名空间)等内容。

JS中实现发布订阅模式和其他语言中还是有区别的,js中使用注册回调函数的方法代理传统的发布订阅模式,js中也无需选择使用推模型还是拉模型,通过函数的arguments可以很方便的表示参数列表,一般选推模型。

优点:时间和对象上解藕等。

缺点:创建订阅者本身消耗一定的时间和内存,但是可能订阅的事件到最后都没有发生,白白浪费了资源;如果过度使用模式也会导致难以追踪bug。

文章作者: 鐔雨
文章链接: https://caichunyu.github.io/2021/12/26/读书笔记-JavaScript设计模式与开发实践-发布订阅模式-观察者模式/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 鐔雨的Blog