iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >如何用JS写一个发布订阅模式
  • 120
分享到

如何用JS写一个发布订阅模式

2023-06-25 12:06:11 120人浏览 泡泡鱼
摘要

这篇文章给大家介绍如何用js写一个发布订阅模式,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。什么是发布订阅模式?能手写实现一下吗?它和观察者模式有区别吗?...1 场景引入我们先来看这么一个场景:假设现在有一个社交平台

这篇文章给大家介绍如何用js写一个发布订阅模式,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

    什么是发布订阅模式?能手写实现一下吗?它和观察者模式有区别吗?...

    1 场景引入

    我们先来看这么一个场景:

    假设现在有一个社交平台,平台上有一个大V叫Nami

    Nami很牛,多才多艺,目前她有2个技能:会写歌、会拍视频

    她会把这些作品发布到平台上。关注她的粉丝就会接收到这些内容

    现在他已经有3个粉丝了,分别是:Luffy、Zoro、Sanji

    每次只要Nami一发布作品,3个粉丝的账号上收到的消息就会更新

    现在用代码来表示:

    const luffy = {  update: function (songs, videos) {    console.log(songs, videos);  },};const zoro = {  update: function (songs, videos) {    console.log(songs, videos);  },};const sanji = {  update: function (songs, videos) {    console.log(songs, videos);  },};const nami = {  // 只要Nami的作品一更新,这个方法就会被调用  workUpdate: function () {    // 获取作品    const songs = this.getSongs();    const videos = this.getVideos();    // 账号更新    luffy.update(songs, videos);    zoro.update(songs, videos);    sanji.update(songs, videos);  },  getSongs: function () {    return "mp3";  },  getVideos: function () {    return "mp4";  },};

    现在问题来了

    • 如果Nami又收获了一个粉丝Robin,我既要添加一个robin对象,又要修改workUpdate方法

    • 如果Nami又有了一项新技能:写小说,我既要修改workUpdate函数,又要修改每个粉丝对象中的update方法,因为参数增加了一个

    发现问题没有?

    粉丝对象和大V对象之间的耦合度太高,导致两者很难各自扩展

    2 代码优化

    2.1 解决增加粉丝问题

    先来解决上述第1个问题,使得增加粉丝的时候不用再修改workUpdate方法

    首先,我们将“大V”抽象成一个类Star,用数组fans来保存粉丝列表,并新增一个添加粉丝的方法addFans

    class Star {  constructor() {    this.fans = [];  }  addFans(fan) {    this.fans.push(fan)  }  workUpdate() {    const songs = this.getSongs();    const videos = this.getVideos();    this.fans.forEach((item) => item.update(songs, videos));  }  getSongs() {    return "MP3";  }  getVideos() {    return "MP4";  }}

    接着,将“粉丝”也抽象成一个类Fan,我们在创建粉丝对象的时候传入“大V”对象,调用该大V的addFans方法来添加到粉丝列表

    class Fan {  constructor(name, star) {    this.name = name    this.star = star    this.star.addFans(this)  }  update(songs, videos) {    console.log(songs, videos);  }}

    现在我们添加粉丝就不必再更改代码了

    const nami = new Star()const luffy = new Fan("luffy", nami);const zoro = new Fan("zoro", nami);const sanji = new Fan("sanji", nami);const robin = new Fan("robin", nami);nami.workUpdate()

    2.2 解决添加作品问题

    我们新增一个works数组来保存大V的作品,并且为其添加getset方法

    class Star {  constructor() {    this.fans = [];    this.works = [];  }  addFans(fan) {    this.fans.push(fan);  }  setWorks(work) {    this.works.push(work);    // 添加作品后,调用更新方法    this.workUpdate();  }  getWorks() {    return this.works;  }  workUpdate() {    this.fans.forEach((item) => item.update());  }}

    对类Fan进行相应修改:

    class Fan {  constructor(name, star) {    this.name = name    this.star = star    this.star.addFans(this)  }  update() {    console.log(`${this.name}:${this.star.getWorks()}`)  }}

    现在大V添加作品就不必再更改代码了:

    const nami = new Star();nami.setWorks('song')nami.setWorks('video')nami.setWorks('novel')const luffy = new Fan("luffy", nami);const zoro = new Fan("zoro", nami);const sanji = new Fan("sanji", nami);nami.workUpdate();

    3 观察者模式

    可以看到,在上述例子中,一个nami对象和多个粉丝对象之间存在着一种一对多的依赖关系,当nami对象有作品更新的时候,所有关注她的粉丝对象都会收到通知。

    事实上,这就是观察者模式

    观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新

    我们将2.2中的代码进行进一步的抽象:

    将“粉丝”看作观察者(Observer),将“大V”看作被观察的对象,称为主题(Subject)

    Subject维护一个观察者列表observerList(原fans数组)。当Subject的状态发生变化(原作品更新)时,通过调用notify(原workUpdate)方法通知所有观察者,执行它们的update方法

    具体代码如下:

    // 被观察者:主题class Subject {  constructor() {    this.observerList = [];    // 代表主题状态    this.state = 0;  }  addObserver(observer) {    this.observerList.push(observer);  }  // 更改主题状态  setState(state) {    this.state = state;    // 状态改变后,通知所有观察者    this.notify();  }  getState() {    return this.state;  }  notify() {    this.observerList.forEach((observer) => observer.update());  }}// 观察者class Observer {  constructor(name, subject) {    this.name = name;    this.subject = subject;    this.subject.addObserver(this);  }  update() {    console.log(`${this.name}:${this.subject.state}`);  }}

    4 经纪人登场

    由于大V业务繁忙,所以他们需要经纪人来维持艺人与粉丝的联系

    经纪人的工作包括:

    • 维护大V的粉丝,经纪人手中会有一个粉丝名单

    • 大V的新作品会交给经纪人,经纪人则负责把新作品发送给粉丝名单中的粉丝

    抽象成一个类,如下:

    class Manager {  constructor() {    this.fans = [];    this.works = [];  }  addFans(fan) {    this.fans.push(fan);  }  setWorks(work) {    this.works.push(work);    // 添加作品后,调用更新方法    this.workUpdate();  }  getWorks() {    return this.works;  }  workUpdate() {    this.fans.forEach((item) => item.update());  }}

    嗯?这段代码貌似在哪儿见过?

    没错,和2.2的Star类一模一样,只不过把类名改了改。

    那这么做有意义吗?

    事实上,代码一模一样是因为在2.2的Star类中我们只写了有关发布(即发布作品)和订阅(即维护粉丝列表)的功能;而Star类本身可能不止这个工作,比如创作内容。

    现在我们将Star类中的发布和订阅的工作抽离出来,交给Manager全权负责。而Star类只要在创作完成后把作品交给Manager就可以了

    另一方面,粉丝Fan也不再直接和Star发生交互了,Fan只关心能不能收到作品,所以Fan直接和Manager发生交互,Fan去订阅(这个行为相当于在Manager维护的粉丝列表中添加粉丝)Manager并从Manager那儿获取想要的作品

    于是Star和Fan的代码如下:

    class Star {  constructor() {}  // 创作  create(manager) {    // 将创作的new work交给经纪人    manager.setWorks("new work");  }}class Fan {  constructor(name, manager) {    this.name = name;    this.manager = manager;    this.manager.addFans(this);  }  update() {    console.log(`${this.name}:${this.manager.getWorks()}`);  }}

    5 发布订阅模式

    前面我们用了经纪人来负责发布和订阅的工作,而不让StarFan发生直接交互,达到了两者解耦的效果

    这就是发布订阅模式

    我们将4中的Manager进行进一步的抽象:

    将“粉丝”看作订阅者(Subscriber);将“大V”看作内容的发布者,在发布订阅模式中称为发布者(Publisher);把“经纪人”看作发布订阅中心(或者说中间人Broker)

    具体代码如下:

    // 发布订阅调度中心class Broker {  constructor() {    this.subscribers = [];    // 代表主题状态    this.state = 0;  }  // 订阅  subscribe(subscriber) {    this.subscribers.push(subscriber);  }  // 更改主题状态  setState(state) {    this.state = state;    // 状态改变后,发布    this.publish();  }  getState() {    return this.state;  }  // 发布  publish() {    this.subscribers.forEach((subscriber) => subscriber.update());  }}// 发布者class Publisher {  constructor() {}  changeState(broker, state) {    broker.setState(state);  }}class Subscriber {  constructor(name, broker) {    this.name = name;    this.broker = broker;    this.broker.subscribe(this);  }  update() {    console.log(`${this.name}:${this.broker.getState()}`);  }}

    来运行一下看看效果:

    // 创建调度中心const broker = new Broker()// 创建发布者const publisher = new Publisher()// 创建订阅者const subscribe1 = new Subscriber('s1', broker)const subscribe2 = new Subscriber('s2', broker)const subscribe3 = new Subscriber('s3', broker)// 发布者改变状态并通知调度中心,调度中心就会通知各个订阅者publisher.changeState(broker, 1)

    6 观察者模式和发布订阅模式的对比

    从角色数量看

    • 观察者模式只有两个角色:观察者和被观察者

    • 发布订阅模式有三个角色:发布者、订阅者以及中间人(发布订阅中心)

    从耦合程度看

    • 观察者模式处于一种松耦合的状态,即两者依然有交互,但是又很容易各自扩展且不相互影响

    • 发布订阅模式中的发布者和订阅者则完全不存在耦合,达到了对象之间解耦的效果

    从意图来看

    • 两者都:实现了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知并自动更新

    关于如何用JS写一个发布订阅模式就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

    --结束END--

    本文标题: 如何用JS写一个发布订阅模式

    本文链接: https://www.lsjlt.com/news/304920.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • 用JS写一个发布订阅模式
      目录1 场景引入2 代码优化2.1 解决增加粉丝问题2.2 解决添加作品问题3 观察者模式4 经纪人登场5 发布订阅模式6 观察者模式和发布订阅模式的对比 什么是发布订阅模式?能手写...
      99+
      2022-11-12
    • 如何用JS写一个发布订阅模式
      这篇文章给大家介绍如何用JS写一个发布订阅模式,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。什么是发布订阅模式?能手写实现一下吗?它和观察者模式有区别吗?...1 场景引入我们先来看这么一个场景:假设现在有一个社交平台...
      99+
      2023-06-25
    • 每天一个设计模式之订阅-发布模式
      博主按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript(_靠这吃饭_)和python(_纯粹喜欢_)两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :) 0. 项目地址 ...
      99+
      2023-01-31
      模式
    • js中发布订阅模式的示例分析
      这篇文章主要介绍js中发布订阅模式的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!代码//发布订阅模式 class EventEmiter{   ...
      99+
      2022-10-19
    • JS前端设计模式之发布订阅模式详解
      目录引言例子1:version1:version2:总结引言 昨天我发布了一篇关于策略模式和代理模式的文章,收到的反响还不错,于是今天我们继续来学习前端中常用的设计模式之一:发布-订...
      99+
      2022-11-13
      JS发布订阅模式 JS前端设计模式
    • vue3如何使用eventBus订阅发布模式
      目录Ⅰ. 什么是eventBus?Ⅱ. vue3 如何使用步骤一 (eventBus 容器)步骤二 ( 订阅者 )步骤三 ( 发布者 )总结Ⅰ. 什么是eventBus? 通俗的讲,...
      99+
      2022-11-13
    • js中发布者订阅者模式的示例分析
      这篇文章主要为大家展示了“js中发布者订阅者模式的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“js中发布者订阅者模式的示例分析”这篇文章吧。发布者订阅...
      99+
      2022-10-19
    • js设计模式之代理模式及订阅发布模式的示例分析
      这篇文章将为大家详细讲解有关js设计模式之代理模式及订阅发布模式的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1,代理模式,只是学习了虚拟代理以及缓存代理,具体...
      99+
      2022-10-19
    • JavaScript利用发布订阅模式编写事件监听函数
      目录背景示例基于Vue的eventHub背景 大家有没有遇到过这种情况,想要写一个事件监听函数,当某个事件被触发的时候,会自动执行这个监听函数,类似: on('changeText'...
      99+
      2023-05-15
      JavaScript实现事件监听函数 JavaScript事件监听函数 JavaScript事件监听
    • JavaScript怎么利用发布订阅模式编写事件监听函数
      这篇“JavaScript怎么利用发布订阅模式编写事件监听函数”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“JavaScri...
      99+
      2023-07-06
    • SpringBoot Redis 发布订阅模式(Pub/Sub)的具体使用
      目录Redis命令行下使用发布订阅 publish 发布 subscribe 订阅 SpringBoot中使用Redis的发布订阅功能 发布者 订阅者 消息监听容器 注意:redis...
      99+
      2022-11-12
    • 如何利用Redis实现分布式消息发布与订阅
      如何利用Redis实现分布式消息发布与订阅引言:在分布式系统中,消息发布与订阅是一种常见的通信模式,可以实现不同模块之间的解耦。Redis作为一种高性能的键值对存储系统,可以用来实现分布式消息发布与订阅功能。本文将介绍如何使用Redis来实...
      99+
      2023-11-07
      分布式 redis 消息发布
    • 怎么使用Node.js的内置模块event实现发布订阅模式
      这篇文章主要介绍了怎么使用Node.js的内置模块event实现发布订阅模式的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么使用Node.js的内置模块event实现发布订阅...
      99+
      2022-10-19
    • vue中消息订阅与发布如何使用
      这篇文章主要介绍“vue中消息订阅与发布如何使用”,在日常操作中,相信很多人在vue中消息订阅与发布如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”vue中消息订阅与发布如何使用”的疑惑有所帮助!接下来...
      99+
      2023-07-05
    • 如何利用Redis和C++开发发布-订阅功能
      如何利用Redis和C++开发发布-订阅功能在开发大规模实时系统时,发布-订阅模式被广泛应用于消息传递和事件驱动机制中。Redis是一个高性能的键值存储系统,通过其提供的发布-订阅功能,可以方便地实现实时通信和数据传递。本文将介绍如何利用R...
      99+
      2023-10-22
      C++ redis 发布订阅
    • C#如何用RabbitMQ实现消息订阅与发布
      这篇文章给大家分享的是有关C#如何用RabbitMQ实现消息订阅与发布的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Fanout交换机模型扇形交换机,采用广播模式,根据绑定的交换机,路由到与之对应的所有队列。一个...
      99+
      2023-06-15
    • 如何利用Redis和C++实现发布-订阅功能
      如何利用Redis和C++实现发布-订阅功能,需要具体代码示例引言:Redis是一种开源的高性能键值存储系统,它支持多种数据结构,并提供了一系列的客户端库,适用于各种编程语言。Redis的发布-订阅功能是其最常用的功能之一,可以实现消息的发...
      99+
      2023-10-22
      C++ redis 发布订阅
    • 如何用Go语言开发一个简单的在线订阅系统
      在当今数字化的时代,订阅系统已经成为各行各业的常见应用,它为企业和个人提供了一种便捷的方式来提供服务和获取信息。而随着技术的不断发展,我们可以利用不同的编程语言来开发各种订阅系统。本篇将介绍如何用Go语言来开发一个简单的在线订阅系统。1. ...
      99+
      2023-11-20
      简单 关键词:Go语言 在线订阅系统
    • 如何使用js写一个js解释器
      这篇文章主要介绍了如何使用js写一个js解释器,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。先来看一下效果一个最简单的解释器上面有提到,js...
      99+
      2022-10-19
    • 如何使用MySQL和Java实现一个简单的订阅功能
      如何使用MySQL和Java实现一个简单的订阅功能随着互联网的发展,订阅功能成为了许多网站和应用程序的常见特性。订阅功能允许用户获取他们感兴趣的内容的更新和通知。在本文中,我将向您介绍如何使用MySQL和Java来实现一个简单的订阅功能。为...
      99+
      2023-10-22
      MySQL Java 订阅功能
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作