前端小白变形记:你要学会这些设计模式!第五弹:发布订阅模式

前言

  1. 从第一篇工厂模式开始,我会持续地更新每一种设计模式的内容,争取用通俗易懂的语言讲解和解释清楚。如果对你学习设计模式有帮助,请不要吝啬手中的赞~ 如果对文章内容有任何疑惑都可以在评论区提出和讨论~

  2. 本系列文章中的完整源码已上传 github 仓库,你可以在这里 github.com/FatMii/Desi...获取。

    同样的,如果对你有帮助,请给我一个star~谢谢

  3. 设计模式合集链接:

    前端小白变形记:你要学会这些设计模式!首发:工厂模式

    前端小白变形记:你要学会这些设计模式!第二弹:单例模式

    前端小白变形记:你要学会这些设计模式!第三弹:责任链模式

    前端小白变形记:你要学会这些设计模式!第四弹:观察者模式

    前端小白变形记:你要学会这些设计模式!第五弹:发布订阅模式

Hello~大家好,前面四篇我们已经学习工厂模式单例模式责任链模式观察者模式观察者模式。本篇我们继续学习第五种设计模式:发布订阅模式

发布订阅模式观察者模式在很多方面确实非常相似,这也是为什么许多开发者很容易混淆这两种模式的原因。两者都是用于在不同组件间实现数据和事件通信的设计模式,但它们在实现细节和使用场景上有着关键的差异。在深入探讨发布订阅模式之前,让我们先回顾一下在上一篇文章中提到的观察者模式的一些缺点。

一、回顾观察者模式实现

javascript 复制代码
// 应用场景:1.dom监听 2.降价商品
class Subject {
  constructor() {
    this.Observers = [];
  }
  add(observer) {
    this.Observers.push(observer);
  }
  remove(observer) {
    this.Observers.filter((item) => item === observer);
  }
  notify() {
    this.Observers.forEach((item) => {
      item.update();
    });
  }
}
//定义观察者对象
class Observer {
  constructor(name) {
    this.name = name;
  }
  update() {
    console.log(`my name is:${this.name}`);
  }
}

let sub = new Subject();
let obs1 = new Observer("observer11");
let obs2 = new Observer("observer22");
sub.add(obs1);
sub.add(obs2);
sub.notify();

二、观察者模式的缺点

缺点一: 无法对事件通知进行细分管控

想象这样一个场景:你是一名专注的程序员,正沉浸在代码中,试图解决一个复杂的问题。突然,"叮咚",你的电脑弹出一个通知:立即召开的公司全体大会。你扫了一眼会议的议题,却发现这次会议与你的工作完全无关。尽管如此,你不得不中断手头的工作,前往会议室。

这就是我们所说的"大喇叭通知法"在作祟。在这种机制下,公司的领导(即老板(Subject))一声令下,所有的员工(即每个人(Observer)),无论是需求分析师、开发人员还是测试工程师,都必须响应这一通知。即便今天的会议内容仅与需求组相关,你这位忙碌的开发人员也不得不放下手中的代码,参加一个与你职责不相关的会议。

这种通知方式不仅效率低下,而且极大地浪费了员工的时间和公司的资源,特别是当涉及到那些与会议主题毫无关联的人员时。它反映出一个问题:通知系统的设计缺乏针对性和细致的分层管理,使得每次广播都无差别地覆盖所有人员,而不考虑信息的相关性或重要性。这不仅打扰了员工的正常工作流程,也可能对工作满意度和整体生产效率产生负面影响。

缺点二:观察者与主题耦合性太高

在观察者模式中,主题观察者之间的关系是紧密且直接的。例如,在一个公司环境里,主题(如公司的管理层)直接管理着所有的观察者(即员工)。这意味着每位员工都需要直接向管理层注册,并保持对其所有指令的警觉。

这种设计虽然确保了信息的快速传递,但同时也带来了一定的弊端。由于观察者需要直接与主题连接,这就增加了双方的依赖性,使得系统的灵活性降低。一旦需要调整或更新系统,每个组件之间的密切关系可能会导致复杂的连锁反应,进而增加管理和维护的难度。例如,简单的调整如增加一个团队成员或改变一个工作流程,都可能需要考虑到对整体系统的潜在影响。

此外,主题需要持续维护和更新其观察者名单,确保在任何关键信息更新时,所有相关人员都能接收到通知。这种管理方式在保持组织结构和信息流动的同时,也可能导致效率低下和资源浪费。

三、发布订阅模式代码实现

我们话不多说,直接上代码看看发布订阅模式和如何解决这个问题的

javascript 复制代码
class PubSub {
    constructor() {
        this.subscribers = {};
    }

    // 订阅方法
    subscribe(event, callback) {
        // 如果没有该事件的订阅者数组,则初始化一个空数组
        if (!this.subscribers[event]) {
            this.subscribers[event] = [];
        }
        // 将回调函数添加到订阅者数组
        this.subscribers[event].push(callback);
        // 返回一个取消订阅的函数
        return () => this.unsubscribe(event, callback);
    }

    // 发布方法
    publish(event, data) {
        // 如果有订阅者,则调用每个回调函数,传入数据
        if (this.subscribers[event]) {
            this.subscribers[event].forEach(callback => callback(data));
        }
    }

    // 取消订阅方法
    unsubscribe(event, callback) {
        if (this.subscribers[event]) {
            // 过滤掉需要取消的回调函数
            this.subscribers[event] = this.subscribers[event].filter(cb => cb !== callback);
        }
    }
}

// 使用例子
const pubsub = new PubSub();

// 订阅事件
const subscription = pubsub.subscribe('message', data => console.log(`Received message: ${data}`));

// 发布事件
pubsub.publish('message', 'Hello world!');

// 取消订阅
subscription(); // 或者 pubsub.unsubscribe('message', callback)

细分事件

在发布订阅模式中,我们使用一个 subscribers 对象来存储事件名和对应的事件处理方法。这种结构与观察者模式中的简单数组相比,提供了更多的灵活性和精确控制。具体来说,subscribers 对象将事件名称映射到一个数组,这个数组包含了所有订阅该事件的方法,如下所示:

javascript 复制代码
{
 'aEvent':[method1,method2],
 'bEvent':[method3,method4],
 'cEvent':[method5,method6]
}

在这种结构下,当 aEvent 事件被触发时,只有 method1method2 会被调用,而其他订阅的处理方法不会受到干扰,从而避免了不必要的操作和资源浪费。这种方法的分离和组织极大提高了系统的效率和响应能力。

新增中间层实现解耦

进一步地,发布订阅模式引入了一个重要的中间层---调度中心,这个中心承担着管理和调度所有事件通知的责任。这一层相当于一个信息交换枢纽,确保了信息从发布者订阅者的有效传递。与观察者模式直接的观察和通知相比,发布订阅模式通过调度中心实现了发布者和订阅者之间的解耦。

总结

发布订阅模式的特点

发布订阅模式作为一种广泛应用于事件驱动架构中的设计模式,具备以下显著特点:

  1. 解耦能力强 :发布者和订阅者之间无需直接通信,他们通过一个中介(调度中心)来交互,这减少了组件间的依赖关系。
  2. 灵活性高:支持动态地添加或移除订阅者,系统可以在运行时适应变化,方便地扩展或修改功能。
  3. 扩展性好:适用于大规模分布式系统,能够有效地处理大量的事件和消息,支持多个订阅者同时监听同一事件。

缺点

尽管发布订阅模式提供了许多优势,但它也有一些潜在的缺点:

  1. 系统复杂性:引入调度中心增加了系统的复杂性,需要额外的维护和管理,可能会增加系统的开发和运行成本。
  2. 资源消耗:维护大量的订阅关系和消息传递可能会消耗较多的计算和存储资源。

结语

发布订阅模式就像是公司里的智能通知系统,它确保只有相关的部门和人员会收到特定会议的通知。这种模式让整个公司的信息流通变得更加高效,因为它避免了不必要的干扰,让每个人都可以专注于对他们真正重要的信息。

想象一下,如果每次公司有个部门会议,无论相关与否,所有员工都收到通知,那会多烦人!但有了发布订阅模式,开发组就不会被不断打扰,去参加只与营销团队相关的策略讨论。这不仅节省了大家的时间,也提高了工作效率。

相关推荐
Martin -Tang2 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
SRY122404193 小时前
javaSE面试题
java·开发语言·面试
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
不二人生6 小时前
SQL面试题——连续出现次数
hive·sql·面试
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui
尝尝你的优乐美6 小时前
vue3.0中h函数的简单使用
前端·javascript·vue.js