JavaScript 设计模式之发布订阅者模式

简介: 前面在文章介绍《JavaScript 设计模式之策略模式》为什么需要设计模式及其一种常见的设计模式。本文继续介绍另一种常见的设计模式发布订阅者模式。

前面在文章介绍《JavaScript 设计模式之策略模式》为什么需要设计模式及其一种常见的设计模式。本文继续介绍另一种常见的设计模式发布订阅者模式。

观察者模式(Observer Pattern)又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。

先来看一个需求,天气预报系统:当极端天气发生时,气象站会发布天气警报。建筑工地、船舶和游客将根据天气数据调整其日程安排。

一旦气象站发出天气警报,会做以下事情:

  • 建筑工地:停工
  • 船舶:系泊
  • 游客:取消行程

如果要编写可用于通知天气警告的代码,改如何来组织?先来看一下代码:

function weatherWarning() {
    buildingsite.stopwork();
    ships.mooring();
    tourists.canceltrip();
}

这是一种直观的写法,但是这种写法有很多不足的地方:

  • 耦合度太高:建筑工地、船舶和游客本来应该是分开的,但现在它们被置于相同的函数中,其中一个对象中的错误可能会导致其他对象无法工作。
  • 违反开闭原则:如果有新的订阅者加入,那么只能修改 weatherWarning 函数。

造成这种现象的原因是气象站承担了主动告知各单位的责任。这就要求气象站必须知道每一个需要了解天气状况的单位。

image.png

仔细想想,其实从逻辑上讲,建筑工地、船舶、游客都应该依靠天气预报,应该是主动积极的一方。按照这个逻辑上面的图最好的方式如下:

image.png

气象站发布通知,然后触发事件,建筑工地、船舶和游客订阅该事件。气象站不需要关心哪些对象关注天气预警,只需要直接触发事件即可。然后需要了解天气状况的单位主动订阅该事件。

这样,气象站与订阅者解耦,订阅者之间也解耦。如果有新的订阅者,那么它只需要直接订阅事件,而不需要修改现有的代码。

为了完成这个发布-订阅系统,需要实现一个事件订阅和分发系统,定义一个时间函数,如下:

const EventEmit = function () {
    this.events = {};
    this.on = function (evtName, callback) {
        const eventHandler = this.events[evtName];
        if (eventHandler) {
            this.events[evtName].push(callback);
        } else {
            this.events[evtName] = [callback];
        }
    };
    this.trigger = function (evtName, ...args) {
        if (this.events[evtName]) {
            this.events[evtName].forEach((eventListener) => {
                eventListener(...args);
            });
        }
    };
};

这样前面的代码可以这样重构:

const weatherEvent = new EventEmit();
weatherEvent.on("warning", function () {
    // buildingsite.stopwork()
    console.log("buildingsite.stopwork()");
});
weatherEvent.on("warning", function () {
    // ships.mooring()
    console.log("ships.mooring()");
});
weatherEvent.on("warning", function () {
    // tourists.canceltrip()
    console.log("tourists.canceltrip()");
});
weatherEvent.trigger("warning");

如果项目中存在多对一的依赖,并且每个模块都相对独立,那么可以考虑使用发布订阅模式来重构代码。而发布订阅模式是前端开发中最常用的设计模式,很多框架都有用到这一设计模式。


相关文章
|
3月前
|
设计模式 前端开发 搜索推荐
前端必须掌握的设计模式——模板模式
模板模式(Template Pattern)是一种行为型设计模式,父类定义固定流程和步骤顺序,子类通过继承并重写特定方法实现具体步骤。适用于具有固定结构或流程的场景,如组装汽车、包装礼物等。举例来说,公司年会节目征集时,蜘蛛侠定义了歌曲的四个步骤:前奏、主歌、副歌、结尾。金刚狼和绿巨人根据此模板设计各自的表演内容。通过抽象类定义通用逻辑,子类实现个性化行为,从而减少重复代码。模板模式还支持钩子方法,允许跳过某些步骤,增加灵活性。
156 11
|
25天前
|
JavaScript 前端开发 Docker
如何通过pm2以cluster模式多进程部署next.js(包括docker下的部署)
通过这些步骤,可以确保您的Next.js应用在多核服务器上高效运行,并且在Docker环境中实现高效的容器化管理。
110 44
|
11天前
|
设计模式 JavaScript 算法
浅谈几种js设计模式
设计模式是软件开发中的宝贵工具,能够提高代码的可维护性和扩展性。通过单例模式、工厂模式、观察者模式和策略模式,我们可以解决不同场景下的实际问题,编写更加优雅和高效的代码。
22 8
|
2月前
|
设计模式
「全网最细 + 实战源码案例」设计模式——模式扩展(配置工厂)
该设计通过配置文件和反射机制动态选择具体工厂,减少硬编码依赖,提升系统灵活性和扩展性。配置文件解耦、反射创建对象,新增产品族无需修改客户端代码。示例中,`CoffeeFactory`类加载配置文件并使用反射生成咖啡对象,客户端调用时只需指定名称即可获取对应产品实例。
90 40
|
2月前
|
设计模式 关系型数据库
「全网最细 + 实战源码案例」设计模式——简单工厂模式
简单工厂模式是一种创建型设计模式,通过工厂类根据传入参数创建不同类型的对象,也称“静态工厂方法”模式。其结构包括工厂类、产品接口和具体产品类。优点是封装性强、代码复用性好;缺点是扩展性差,增加新产品时需修改工厂类代码,违反开闭原则。适用于对象种类较少且调用者无需关心创建细节的场景。
57 19
|
2月前
|
设计模式 数据安全/隐私保护
Next.js 实战 (七):浅谈 Layout 布局的嵌套设计模式
这篇文章介绍了在Next.js框架下,如何处理中后台管理系统中特殊页面(如登录页)不包裹根布局(RootLayout)的问题。作者指出Next.js的设计理念是通过布局的嵌套来创建复杂的页面结构,这虽然保持了代码的整洁和可维护性,但对于特殊页面来说,却造成了不必要的布局包裹。文章提出了一个解决方案,即通过判断页面的skipGlobalLayout属性来决定是否包含RootLayout,从而实现特殊页面不包裹根布局的目标。
99 33
|
2月前
|
设计模式 Java
「全网最细 + 实战源码案例」设计模式——生成器模式
生成器模式(Builder Pattern)是一种创建型设计模式,用于分步骤构建复杂对象。它允许用户通过控制对象构造的过程,定制对象的组成部分,而无需直接实例化细节。该模式特别适合构建具有多种配置的复杂对象。其结构包括抽象建造者、具体建造者、指挥者和产品角色。适用于需要创建复杂对象且对象由多个部分组成、构造过程需对外隐藏或分离表示与构造的场景。优点在于更好的控制、代码复用和解耦性;缺点是增加复杂性和不适合简单对象。实现时需定义建造者接口、具体建造者类、指挥者类及产品类。链式调用是常见应用方式之一。
56 12
|
2月前
|
设计模式 关系型数据库
「全网最细 + 实战源码案例」设计模式——工厂方法模式
简单工厂模式是一种创建型设计模式,通过一个工厂类根据传入参数创建不同类型的产品对象,也称“静态工厂方法”模式。其结构包括工厂类、产品接口和具体产品类。适用于创建对象种类较少且调用者无需关心创建细节的场景。优点是封装性强、代码复用性好;缺点是扩展性差,增加新产品时需修改工厂类代码,违反开闭原则。
52 15
|
3月前
Next.js 实战 (三):优雅的实现暗黑主题模式
这篇文章介绍了在Next.js中实现暗黑模式的具体步骤。首先,需要安装next-themes库。然后,在/components/ThemeProvider/index.tsx文件中新增ThemeProvider组件,并在/app/layout.tsx文件中注入该组件。如果想要加入过渡动画,可以修改代码实现主题切换时的动画效果。最后,需要在需要的位置引入ThemeModeButton组件,实现暗黑模式的切换。
|
4月前
|
设计模式 前端开发 JavaScript
JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式
本文深入探讨了JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式,结合电商网站案例,展示了设计模式如何提升代码的可维护性、扩展性和可读性,强调了其在前端开发中的重要性。
61 2