首页 > 其他分享 >【面试题】说说你对发布订阅、观察者模式的理解?区别?

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

时间:2023-01-26 15:06:33浏览次数:49  
标签:订阅 面试题 const name type 观察者 TYPE



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


大厂面试题分享 面试题库

前端面试题库 (面试必备)

地址:​​前端面试题库​

一、观察者模式


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

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



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


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

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

实现代码如下:

被观察者模式

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');

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

二、发布订阅模式


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

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



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


实现代码如下:

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);

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

三、区别


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

  • 观察者模式:某公司给自己员工发月饼发粽子,是由公司的行政部门发送的,这件事不适合交给第三方,原因是“公司”和“员工”是一个整体
  • 发布-订阅模式:某公司要给其他人发各种快递,因为“公司”和“其他人”是独立的,其唯一的桥梁是“快递”,所以这件事适合交给第三方快递公司解决

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

两者区别如下图:



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


  • 在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。
  • 在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。
  • 观察者模式大多数时候是同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)

标签:订阅,面试题,const,name,type,观察者,TYPE
From: https://blog.51cto.com/u_14627797/6023538

相关文章

  • 【综合笔试题】难度 2/5,简单且经典面试题
    题目描述这是LeetCode上的​​870.优势洗牌​​,难度为中等。Tag:「红黑树」、「哈希表」、「排序」、「双指针」、「贪心」给定两个大小相等的数组 ​​nums1​​......
  • 微软面试题
    例题1:为什么下水道的盖子是圆的?回答案例它们并不都是圆的,有些是方的。的确有些圆井盖,但我也看过方的、长方的。试题点评该求职者的回答巧妙之处在于敢于提出自己的看法,而不......
  • 【java面试题】lock和synchronized有什么区别?
    学习目标:掌握lock与synchronized的区别理解ReentrantLock的公平、非公平锁理解ReentrantLock中的条件变量lock与synchronized的区别有三个层面学习内容:1.......
  • Vue中的 消息订阅与发布(pubsub)
    1:内容说明:2:界面示例:......
  • 前端面试题 - javaScript系列
    Time:2023-01-2021:14:37ES6系列1.说说var、let、const之间的区别var、let、const三者区别可以围绕下面五点展开:变量提升暂时性死区块级作用域重复声明修......
  • 面试题-索引设计的原则
    索引设计的原则针对于数据量较大,且查询比较频繁的表建立索引。针对于常作为查询条件(where)、排序(orderby)、分组(groupby)操作的字段建立索引。尽量选择区分度高......
  • LeetCode.面试题02.05-链表求和-题解分析
    题目来源面试题02.05.链表求和题目详情给定两个用链表表示的整数,每个节点包含一个数位。这些数位是反向存放的,也就是个位排在链表首部。编写函数对这两个整数求和,并......
  • 前端面试题合集-第一篇
    前端面试题合集-第一篇......
  • 面试题-什么是最左前缀法则?什么时候索引将失效?
    什么是最左前缀法则?什么时候索引将失效?如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,索......
  • 2022最新MySQL高频面试题汇总
    sidebar:heading事务的四大特性?事务特性ACID:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。原子性是指事务包含的所有操作要么全部成......