美文网首页vue的响应式
JS设计模式之订阅发布模式

JS设计模式之订阅发布模式

作者: Splendid飞羽 | 来源:发表于2021-05-09 21:48 被阅读0次

定义:订阅发布模式定义了对象间一种一对多的关系,让多个观察者对象同时监听同一主题对象,当一个对象改变时,所有依赖于它的对象都将得到通知。

优点:

  • 支持单一广播通信,当对象的状态发生变化时,会自动通知订阅它的对象。
  • 发布者与订阅者的耦合性降低,发布者只关注发布的消息,订阅者只关注订阅的消息

缺点

  • 消耗一定的时间和内存
  • 可以弱化对象之间的联系,但是过度使用会造成代码难以维护和理解。

核心:订阅者、发布者

1、实现原理:
  • 确定谁是发布者
  • 给发布者增加一个缓存列表,用来缓存回调函数来通知订阅者
  • 最后就是发布消息,发布者遍历这个列表,依次触发里面存放的订阅者的回调函数,来通知订阅者。

下面是一个简单的订阅发布的js示例

var shoeObj = {}; // 定义发布者
shoeObj.list = []; // 缓存列表 存放订阅者回调函数
        
// 增加订阅者
shoeObj.listen = function(fn) {
    shoeObj.list.push(fn);  // 订阅消息添加到缓存列表
}

// 发布消息
shoeObj.trigger = function(){
    for(var i = 0,fn; fn = this.list[i++];) {
        fn.apply(this,arguments); 
    }
}
// 小红订阅如下消息
shoeObj.listen(function(color,size){
    console.log("颜色是:"+color);
    console.log("尺码是:"+size);  
});

// 小花订阅如下消息
shoeObj.listen(function(color,size){
    console.log("再次打印颜色是:"+color);
    console.log("再次打印尺码是:"+size); 
});
shoeObj.trigger("红色",40);
shoeObj.trigger("黑色",42);
// 颜色是:红色
// 尺码是:40
// 再次打印颜色是:红色
// 再次打印尺码是:40
// 颜色是:黑色
// 尺码是:42
// 再次打印颜色是:黑色
// 再次打印尺码是:42

参考我的印象笔记

2、源码中的发布-订阅模式**

发布-订阅模式在源码中应用很多,特别是现在很多前端框架都会有的双向绑定机制的场景,这里以现在很火的 Vue 为例,来分析一下 Vue 是如何利用发布-订阅模式来实现视图层和数据层的双向绑定。先借用官网的双向绑定原理图:

image

下面稍微解释一下这个图(框架源码整个过程比较复杂,如果现在看不懂下面几段也没关系,大致了解一下即可)。

组件渲染函数(Component Render Function)被执行前,会对数据层的数据进行响应式化。响应式化大致就是使用 Object.defineProperty 把数据转为 getter/setter,并为每个数据添加一个订阅者列表的过程。这个列表是 getter 闭包中的属性,将会记录所有依赖这个数据的组件。

  • 也就是说,响应式化后的数据相当于发布者。
  • 每个组件都对应一个 Watcher 订阅者。当每个组件的渲染函数被执行时,都会将本组件的 Watcher 放到自己所依赖的响应式数据的订阅者列表里,这就相当于完成了订阅,一般这个过程被称为依赖收集(Dependency Collect)。
  • 组件渲染函数执行的结果是生成虚拟 DOM 树(Virtual DOM Tree),这个树生成后将被映射为浏览器上的真实的 DOM 树,也就是用户所看到的页面视图。
  • 当响应式数据发生变化的时候,也就是触发了 setter 时,setter 会负责通知(Notify)该数据的订阅者列表里的 WatcherWatcher 会触发组件重渲染(Trigger re-render)来更新(update)视图。

我们可以看看 Vue 的源码:

// src/core/observer/index.js 响应式化过程

Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
        // ...
        const value = getter ? getter.call(obj) : val // 如果原本对象拥有getter方法则执行
        dep.depend()                     // 进行依赖收集,dep.addSub
        return value
    },
    set: function reactiveSetter(newVal) {
        // ...
        if (setter) { setter.call(obj, newVal) }    // 如果原本对象拥有setter方法则执行
        dep.notify()               // 如果发生变更,则通知更新
    }
})

而这个 dep 上的 dependnotify 就是订阅和发布通知的具体方法。

  • 简单来说,响应式数据是消息的发布者,而视图层是消息的订阅者,如果数据更新了,那么发布者会发布数据更新的消息来通知视图更新,从而实现数据层和视图层的双向绑定。

3、发布-订阅模式的优缺点

发布-订阅模式最大的优点就是解耦:

  • 时间上的解耦 :注册的订阅行为由消息的发布方来决定何时调用,订阅者不用持续关注,当消息发生时发布者会负责通知;
  • 对象上的解耦 :发布者不用提前知道消息的接受者是谁,发布者只需要遍历处理所有订阅该消息类型的订阅者发送消息即可(迭代器模式),由此解耦了发布者和订阅者之间的联系,互不持有,都依赖于抽象,不再依赖于具体;
  • 由于它的解耦特性,发布-订阅模式的使用场景一般是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变。发布-订阅模式还可以帮助实现一些其他的模式,比如中介者模式。

发布-订阅模式也有缺点:

  • 增加消耗 :创建结构和缓存订阅者这两个过程需要消耗计算和内存资源,即使订阅后始终没有触发,订阅者也会始终存在于内存;
  • 增加复杂度 :订阅者被缓存在一起,如果多个订阅者和发布者层层嵌套,那么程序将变得难以追踪和调试,参考一下 Vue 调试的时候你点开原型链时看到的那堆 deps/subs/watchers 们…
  • 缺点主要在于理解成本、运行效率、资源消耗,特别是在多级发布-订阅时,情况会变得更复杂。
4、发布订阅模式与其他设计模式的区别

发布-订阅模式和观察者模式

观察者模式与发布-订阅者模式,在平时你可以认为他们是一个东西,但是某些场合(比如面试)下可能需要稍加注意,借用网上一张流行的图:

image

区别主要在发布-订阅模式中间的这个 Event Channel:

  • 观察者模式 中的观察者和被观察者之间还存在耦合,被观察者还是知道观察者的;
  • 发布-订阅模式 中的发布者和订阅者不需要知道对方的存在,他们通过消息代理来进行通信,解耦更加彻底;

发布-订阅模式和责任链模式

发布-订阅模式和责任链模式也有点类似,主要区别在于:

  • 发布-订阅模式 传播的消息是根据需要随时发生变化,是发布者和订阅者之间约定的结构,在多级发布-订阅的场景下,消息可能完全不一样;
  • 责任链模式 传播的消息是不变化的,即使变化也是在原来的消息上稍加修正,不会大幅改变结构;

任务:手写发布订阅模式

相关文章

  • Javaの设计模式之观察者模式

    推荐阅读:《设计模式之禅》 Observer Pattern 设计模式之观察者模式(发布订阅模式) Demo gi...

  • js设计模式之发布-订阅模式

    简单版 升级版-增加命名空间和先发布后订阅的功能

  • JS设计模式之订阅发布模式

    定义:订阅发布模式定义了对象间一种一对多的关系,让多个观察者对象同时监听同一主题对象,当一个对象改变时,所有依赖于...

  • JS设计模式--发布/订阅模式

    一、前言 JS语言的执行环境是“单线程”,所以任务是一个一个进行执行,如果任务多就需要排队。如果任务多,浏览器加载...

  • js常见设计模式

    1.写出 构造函数模式、混合模式、模块模式、工厂模式、单例模式、发布订阅模式的范例。 JS设计模式大全 构造函数模...

  • JS设计模式-发布订阅

    发布订阅 比如一个公众号可以被多个用户同时订阅,当公众号有新增内容时候,只要发布就好了,用户就能接收到最新的内容。...

  • JS设计模式七:发布-订阅模式

    发布-订阅模式简述 发布---订阅模式又叫观察者模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某...

  • 设计模式之发布订阅模式

    最近公司在进行设计模式的分享,形成文章记录下来,同时也是对自己学习的总结,便于回顾,以及与大家交流。 定义 他定义...

  • 设计模式之发布 — 订阅模式

    发布 — 订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对...

  • JavaJavascript基础进阶(十七)JS中常用的设计模式

    单利设计模式、构造原型设计模式、发布订阅设计模式、promise设计模式 单利模式 构造原型设计模式 最贴近OOP...

网友评论

    本文标题:JS设计模式之订阅发布模式

    本文链接:https://www.haomeiwen.com/subject/ndpvdltx.html