【面试题】说说你对发布订阅、观察者模式的理解?区别?

news2025/1/18 11:46:53

大厂面试题分享 面试题库

前端面试题库 (面试必备) 推荐:★★★★★

地址:前端面试题库

一、观察者模式


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

观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯

例如生活中,我们可以用报纸期刊的订阅来形象的说明,当你订阅了一份报纸,每天都会有一份最新的报纸送到你手上,有多少人订阅报纸,报社就会发多少份报纸

报社和订报纸的客户就形成了一对多的依赖关系

实现代码如下:

被观察者模式

class Subject {

  constructor() {
    this.observerList = [];
  }

  addObserver(observer) {
    this.observerList.push(observer);
  }

  removeObserver(observer) {
    const index = this.observerList.findIndex(o => o.name === observer.name);
    this.observerList.splice(index, 1);
  }

  notifyObservers(message) {
    const observers = this.observeList;
    observers.forEach(observer => observer.notified(message));
  }

}

观察者:

class Observer {

  constructor(name, subject) {
    this.name = name;
    if (subject) {
      subject.addObserver(this);
    }
  }

  notified(message) {
    console.log(this.name, 'got message', message);
  }
}

使用代码如下:

const subject = new Subject();
const observerA = new Observer('observerA', subject);
const observerB = new Observer('observerB');
subject.addObserver(observerB);
subject.notifyObservers('Hello from subject');
subject.removeObserver(observerA);
subject.notifyObservers('Hello again');

上述代码中,观察者主动申请加入被观察者的列表,被观察者主动将观察者加入列表

二、发布订阅模式


发布-订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在

同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者存在

实现代码如下:

class PubSub {
  constructor() {
    this.messages = {};
    this.listeners = {};
  }
  // 添加发布者
  publish(type, content) {
    const existContent = this.messages[type];
    if (!existContent) {
      this.messages[type] = [];
    }
    this.messages[type].push(content);
  }
  // 添加订阅者
  subscribe(type, cb) {
    const existListener = this.listeners[type];
    if (!existListener) {
      this.listeners[type] = [];
    }
    this.listeners[type].push(cb);
  }
  // 通知
  notify(type) {
    const messages = this.messages[type];
    const subscribers = this.listeners[type] || [];
    subscribers.forEach((cb, index) => cb(messages[index]));
  }
}

发布者代码如下:

class Publisher {
  constructor(name, context) {
    this.name = name;
    this.context = context;
  }
  publish(type, content) {
    this.context.publish(type, content);
  }
}

订阅者代码如下:

class Subscriber {
  constructor(name, context) {
    this.name = name;
    this.context = context;
  }
  subscribe(type, cb) {
    this.context.subscribe(type, cb);
  }
}

使用代码如下:

const TYPE_A = 'music';
const TYPE_B = 'movie';
const TYPE_C = 'novel';

const pubsub = new PubSub();

const publisherA = new Publisher('publisherA', pubsub);
publisherA.publish(TYPE_A, 'we are young');
publisherA.publish(TYPE_B, 'the silicon valley');
const publisherB = new Publisher('publisherB', pubsub);
publisherB.publish(TYPE_A, 'stronger');
const publisherC = new Publisher('publisherC', pubsub);
publisherC.publish(TYPE_C, 'a brief history of time');

const subscriberA = new Subscriber('subscriberA', pubsub);
subscriberA.subscribe(TYPE_A, res => {
  console.log('subscriberA received', res)
});
const subscriberB = new Subscriber('subscriberB', pubsub);
subscriberB.subscribe(TYPE_C, res => {
  console.log('subscriberB received', res)
});
const subscriberC = new Subscriber('subscriberC', pubsub);
subscriberC.subscribe(TYPE_B, res => {
  console.log('subscriberC received', res)
});

pubsub.notify(TYPE_A);
pubsub.notify(TYPE_B);
pubsub.notify(TYPE_C);

上述代码,发布者和订阅者需要通过发布订阅中心进行关联,发布者的发布动作和订阅者的订阅动作相互独立,无需关注对方,消息派发由发布订阅中心负责

三、区别


两种设计模式思路是一样的,举个生活例子:

  • 观察者模式:某公司给自己员工发月饼发粽子,是由公司的行政部门发送的,这件事不适合交给第三方,原因是“公司”和“员工”是一个整体

  • 发布-订阅模式:某公司要给其他人发各种快递,因为“公司”和“其他人”是独立的,其唯一的桥梁是“快递”,所以这件事适合交给第三方快递公司解决

上述过程中,如果公司自己去管理快递的配送,那公司就会变成一个快递公司,业务繁杂难以管理,影响公司自身的主营业务,因此使用何种模式需要考虑什么情况两者是需要耦合的

两者区别如下图:

  • 在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。

  • 在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。

  • 观察者模式大多数时候是同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)

大厂面试题分享 面试题库

前端面试题库 (面试必备) 推荐:★★★★★

地址:前端面试题库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/155579.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Elasticsearch-高级搜索(拼音|首字母|简繁|二级搜索)

需求: 中文搜索、英文搜索、中英混搜全拼搜索、首字母搜索、中文全拼、中文首字母混搜简繁搜索二级搜索(对第一次搜索结果,再进行搜索)一、ES相关插件 IK分词: GitHub - medcl/elasticsearch-analysis-ik: The IK A…

JsonWebToken远程代码执行漏洞(CVE-2022-23529)

漏洞描述 JsonWebToken 是一个用于创建、签名和验证 JSON Web Token开源库。node-jsonwebtoken是node.js 下 JsonWebToken 的实现。 在JsonWebToken < 8.5.1版本中由于jwt.verify()方法未对用户输入的secretOrPublicKey参数进行有效的检查。如果攻击者能够控制secretOrPub…

【docker12】docker复杂安装

docker复杂安装 之前是单机版&#xff0c;自娱自乐还是不错滴&#xff0c;但是如果是生产开发环境中是需要复杂集群安装的 1.安装mysql主从复制 1.1主从复制原理&#xff08;记得补&#xff09; 1.2主从搭建步骤 新建主服务器容器实例3307 命令&#xff1a; docker run -d …

Unity 实现一个特定动画状态切换树

前言 今天在工作中接到一需求,要求人物摆在不同的9个格子上,在哪个格子上,就走哪个格子动画播放逻辑; 打个比方:第一个格子上有台电脑,我将角色放上去,角色就玩电脑,每播完一次动画,就根据概率判断是否需要去喝水,最终实现的效果,就是将角色放上去,并且随机时间进行喝水;第二个…

TiDB 底层存储结构 LSM 树原理介绍

随着数据量的增大&#xff0c;传统关系型数据库越来越不能满足对于海量数据存储的需求。对于分布式关系型数据库&#xff0c;我们了解其底层存储结构是非常重要的。本文将介绍下分布式关系型数据库 TiDB 所采用的底层存储结构 LSM 树的原理。 1 LSM 树介绍 LSM 树&#xff08…

测试开发基础 mvn test | 利用 Maven Surefire Plugin 做测试用例基础执行管理

一、需求在测试工作场景中&#xff0c;经常会遇到下面的问题&#xff1a;1、执行自动化测试用例的时候&#xff0c;只想指定某个测试类&#xff0c;或者某个方法&#xff0c;又或者某一类用例等&#xff0c;怎么办&#xff1f;2、想要和 Jenkins 一起进行持续集成&#xff0c;可…

C语言_文件操作(下)

目录 8. 文件的随机读写 8.1 fseek 8.2 ftell 8.3 rewind ​9. 文件结束判定 10. perror 8. 文件的随机读写 假设文件中存放的是abcdef&#xff0c;如下图&#xff0c;通常在读文件时&#xff0c;是先读取首元素地址&#xff0c;也就是文件指针指向a&#xff0c;每读一…

【Linux进程信号】

Linux进程信号技术应用角度的信号信号的发送与记录信号处理常见方式产生信号通过终端按键产生信号通过系统函数向进程发信号由软件条件产生信号由硬件异常产生信号阻塞信号信号其他相关常见概念在内核中的表示sigset_t信号集操作函数sigprocmasksigpending捕捉信号内核空间与用…

three.js 之 入门篇 5之几何体的认知( 顶点创建矩阵、炫酷三角形科技物体、基础网格材质 material )

目录three.js 之 入门篇 5之几何体的认知01BufferGeometry设置顶点创建矩阵02 生产炫酷三角形科技物体03 常见的网格几何体 geometry04 基础网格材质 material04-1 初识别材质与纹理04-2 初识别材质与纹理 &#xff08; 平移、旋转 &#xff09;04-3 纹理显示设置&#xff08; …

C语言——指针面试题详解

&#x1f412;个人主页&#xff1a;平凡的小苏&#x1f4da;学习格言&#xff1a;别人可以拷贝我的模式&#xff0c;但不能拷贝我不断往前的激情目录 1. 指针和数组笔试题解析 一维数组 字符数组 二维数组 2. 指针笔试题 笔试题1&#xff1a; 笔试题2&#xff1a; 笔试题…

ffmpeg 颜色空间转换分析

颜色空间转换有很多相关标准&#xff1a; https://docs.opencv.org/3.4.0/de/d25/imgproc_color_conversions.html https://www.itu.int/rec/R-REC-BT.601-4-199407-S/en ffmpeg命令行颜色空间转换是通过调用vf_scale中的swscale来进行转码。 我们通过gdb来调试ffmpeg. 首先编译…

《Getting Started with NLP》chap11:Named-entity recognition

《Getting Started with NLP》chap11&#xff1a;Named-entity recognition 最近需要做一些NER相关的任务&#xff0c;来学习一下这本书的第十一章 文章目录《Getting Started with NLP》chap11&#xff1a;Named-entity recognition11.1 Named entity recognition: Definition…

jar转成dex文件

jar转成dex文件 dx 可以利用android studio中的dx工具。 可以看到android的tool安装位置: 在此路径下的如下目录有dx.bat,这个正是我们需要使用的工具。 D:\sdk\build-tools\30.0.3将dx.bat添加到环境变量 基本指令 > dx --dex --output 输出路径 待转化的jar包C

高性能网络模式:Reactor 和 Proactor

文章目录演进多 Reactor 多进程 / 线程Proactor总结演进 如果要让服务器服务多个客户端&#xff0c;那么最直接的方式就是为每一条连接创建线程。其实创建进程也是可以的&#xff0c;原理是一样的&#xff0c;进程和线程的区别在于线程比较轻量级些&#xff0c;线程的创建和线…

【Dash搭建可视化网站】项目12:全球恐怖主义数据大屏制作步骤详解

全球恐怖主义数据大屏制作步骤详解1 项目效果图2 项目架构3 文件介绍和功能完善3.1 assets文件夹介绍3.2 app.py和index.py文件完善3.3 header.py文件完善3.4 filteritem.py文件完善3.5 api.py文件和api.ipynb文件完善3.6 staclbarline.py文件完善3.7 piechart.py文件完善3.8 m…

IO多路复用之select、poll、epoll之间的区别总结

一、IO多路复用基本概念 select、poll、epoll都是IO多路复用的机制。IO多路复用就是通过一种机制&#xff0c;让一个进程/线程可以监视多个描述符&#xff0c;一旦某个描述符就绪&#xff08;一般是读写就绪&#xff09;&#xff0c;能够通知应用程序进行相应的读写操作。 I/…

并网逆变器学习笔记5---三电平DPWM

参考文献&#xff1a;《中压三电平全功率风电变流器关键技术研究---任康乐》 1、调制策略分析 DPWM由于其在任意时刻均有一相钳位在某个电平&#xff0c;使得该相的功率器件不发生开关动作&#xff0c;因而可以大大降低开关损耗&#xff08;平均降低1/3&#xff09;&#xff…

Java多线程案例——定时器

一&#xff0c;定时器1.定时器的概念定时器是Java开发中一个重要的组件&#xff08;功能类似于闹钟&#xff09;&#xff0c;可以指定一个任务在多长时间后执行&#xff08;尤其在网络编程的时候&#xff0c;如果网络卡顿很长时间没有响应用户的需求&#xff0c;此时可以使用定…

分享|UWB使用频段大幅收窄,新标准对于行业发展是好是坏?

近日&#xff0c;工信部无线电管理局发布了《超宽带&#xff08;UWB&#xff09;设备无线电管理规定&#xff08;征求意见稿&#xff09;》&#xff08;以下简称“新版《规定》”&#xff09;。 根据新版《规定》&#xff0c;未来国内UWB技术的使用频段为&#xff1a;7235-875…

seo的基本知识(概述网站内部优化和外部优化)

了解网站外部优化的4大重点 网站优化的时候都会重视网站的外部优化&#xff0c;所以网站外部优化的4大重点&#xff01;今天就来和大家说一说&#xff01; 1.高质量的内容和外链 未来的SEO道路高质量的有价值的内容是非常重要的&#xff0c;还有就是高质量的外链也是重要之…