海为什么是蓝色的| 白细胞是什么意思| 毛肚是什么东西| 魔术贴是什么| 1997年属牛是什么命| 辩驳是什么意思| 直男什么意思| 大便羊粪状吃什么药| 青少年吃什么钙片有助于长高| 男人吃海参有什么好处| whoo是什么牌子| 最好的烟是什么牌子| 晒伤擦什么药| 入木三分是什么意思| 8月28日什么星座| 气加山念什么| 糖料病者应吃什么好| soeasy是什么意思| 什么的关系| 手上长斑点是什么原因| 发烧能吃什么食物| 肺结核早期有什么症状| 夜宵和宵夜有什么区别| 什么叫伴手礼| 梦见别人家办丧事是什么意思| 4b橡皮和2b橡皮有什么区别| 封建思想是什么意思| 结核是什么| 慢性疾病都包括什么病| 娘是什么意思| igm是什么| 咳血是什么原因引起的| 花枝招展什么意思| 肚子突然疼是什么原因| 脑花是什么东西| 肾功能不全是什么意思| 天女散花是什么意思| 什么生肖名扬四海| 脾切除后有什么影响和后遗症| 纪梵希属于什么档次| 嘴里起血泡是什么原因| 老打瞌睡犯困是什么原因| 红粉是什么意思| 山开念什么| 盆腔炎用什么药最好| 9月13日什么星座| 磁共振检查什么| 囊性灶什么意思严重吗| 猫瘟吃什么药| 男人性功能不好吃什么药| 肝火旺盛失眠吃什么药| 吃了虾不能吃什么水果| 什么血型会导致不孕| pdd是什么意思| 一比吊糟什么意思| 手指起倒刺是什么原因| 蚂蚁搬家是什么意思| 囊肿吃什么药| 90岁属什么生肖| 什么是普惠性幼儿园| 发财树用什么肥料最好| 神经内科和神经外科有什么区别| 头发长得慢是什么原因| 黑裙子配什么鞋子| 小确幸什么意思| mrna是什么| 女性白带多吃什么药| 甲状腺结节吃什么水果好| 头寸是什么意思| 大什么针| 面碱是什么| 什么的蹲着| 痔疮是什么症状| 六月二十三是什么日子| 熙熙攘攘什么意思| 二尖瓣反流吃什么药| 什么是庞氏骗局| 南海龙王叫什么| 梦见老人去世预示什么| 60年属鼠是什么命| 巨蟹和什么星座最配| 容颜是什么意思| 双侧乳腺小叶增生是什么意思| 食邑万户是什么意思| biu是什么意思| 子女缘薄是什么意思| 搞怪是什么意思| 双鱼座的幸运石是什么| 岁运并临是什么意思| 588是什么意思| 做穿刺是什么意思| 梦见死去的姥姥是什么意思| 左侧肋骨下面是什么器官| 加拿大签证需要什么材料| 道地是什么意思| 沉鱼落雁什么意思| 0中间有一横是什么字体| 咳嗽可以吃什么| 1941年是什么年| 什么是干眼症| 耳什么目明| 落枕吃什么药| 男孩适合学什么专业| 4090是什么意思| 喉咙突然哑了什么原因| 什么药不能喝酒| 四川芽菜是什么菜| 强直性脊柱炎吃什么药| 奶奶的弟弟叫什么| 孕妇抽筋是什么原因引起的| 今年22岁属什么| 鸡婆是什么意思| 头孢吃多了有什么副作用| 半夜是什么时辰| 92年的属什么生肖| 蜂蜜水有什么好处| 甲功七项挂什么科| 蚊虫叮咬过敏用什么药| 肚脐眼上方是什么器官| 血小板减少吃什么| 经常放屁吃什么药好| 胃不好早餐吃什么好| 翠绿色配什么颜色好看| 胖子从12楼掉下来会变什么| 促销是什么意思| 怀孕胎盘低有什么影响| 菜心是什么菜的心| 11月10号是什么星座| 捡到黄金是什么预兆| 结核抗体弱阳性什么意思| 肠胃不好吃什么药最好| 护理和护士有什么区别| 来褐色分泌物是什么原因| 鸡炖什么好吃| 西地那非有什么副作用| 下午六点是什么时辰| 中风是什么原因引起的| 人生导师是什么意思| 第一次做什么感觉| 1988年出生是什么命| 骨挫伤是什么意思| 白带发黄是什么原因引起的| 看好你是什么意思| 王八吃什么| 三无产品是指什么| 软柿子是什么意思| 轻度抑郁有什么症状| superman什么意思| 肾虚吃什么药最有效| 正常的白带是什么样的| 血淋是什么意思| 刘德华属什么生肖| 冰箱保鲜室不制冷是什么原因| 孕妇梦见老鼠是什么意思| 月亮象征着什么| hold住是什么意思| 睡眠模式是什么意思| 眼睛淤青用什么方法能快点消除| 甲状腺功能亢进吃什么药| 匝道是什么| 饱和脂肪是什么意思| 幼对什么| 佩戴朱砂有什么好处| 79是什么意思| 验孕棒一深一浅是什么意思| 诺如病毒吃什么药好得快一点| 豆浆不能和什么一起吃| 猪和什么属相不合| 天丝是什么材质| 梦见骆驼是什么意思| 淋巴结是什么病| 遥遥相望是什么意思| 白眼狼什么意思| 女性私处长痘痘是什么原因| 摩羯后面是什么星座| 咽喉疼吃什么药| 淋巴结肿吃什么消炎药| flour是什么意思| 娃娃脸是什么脸型| 最大的荔枝是什么品种| 帕罗西汀是什么药| 布病是什么| 乳腺增生吃什么| 和什么相什么| 贫血四项是指什么检查| 吴亦凡属什么| 洗衣机启动不了是什么原因| 肩胛骨疼痛是什么原因| 支原体弱阳性是什么意思| 减肥什么时候喝牛奶| 甲亢吃什么盐好| 玉米吃多了有什么坏处| 1945年属什么| 风月是什么意思| 吃木瓜有什么作用| 村支部书记是什么级别| 什么是痤疮图片| 为什么会一直咳嗽| spank是什么意思| 什么的问题| 胰岛a细胞分泌什么激素| 眉毛旁边长痘痘是什么原因| 勤代表什么生肖| 妈妈过生日送什么礼物好| 每天吃一个西红柿有什么好处| 喉咙干是什么病的前兆| 膀胱破裂什么症状| 病毒性感冒发烧吃什么药| 龙涎香是什么东西| 乙肝e抗体高是什么意思| 后中长是什么意思| 西洋参泡水喝有什么好处| aah是什么意思| 痛风打什么针| 下午5点是什么时辰| 什么时候普及高中义务教育| 凝血酶原时间是什么意思| 新生儿痤疮是什么引起的| 眼睛不能见光是什么病| 胆囊结石不能吃什么| 母鸡是什么意思| 浆果是什么| 神的国和神的义指的是什么| 胃炎吃什么药最有效| 口腔癌早期有什么征兆| 五粮液是什么香型的酒| 雅痞是什么意思| 什么时辰出生的人命好| 男士蛋皮痒用什么药| 7月去青海带什么衣服| 什么是介入治疗| 嗝屁是什么意思| 昂字五行属什么| 小便粉红色是什么原因| 大疱病是什么病| 什么叫引流| 自负什么意思| 子宫腺肌症是什么原因引起的| 喝什么解暑| 看脊椎挂什么科| 公章一般是什么字体| ds是什么意思| 不想怀孕有什么办法| 肠胃炎可以吃什么水果| 中老年吃什么钙片比较好| 萎缩性胃炎用什么药最好| 胃疼和肚子疼有什么区别| 献血后吃什么补血最快| 西铁城是什么档次的表| 上四休二是什么意思| h1v是什么病| 为什么会眼压高| 脸上肉跳动是什么原因| 背疼是什么原因引起的女人| 哎呀是什么意思| 什么茶叶降血压最好| 为什么总是做梦| only是什么品牌| 痛风打什么针| mono是什么意思| 导管是什么| 股癣是什么原因引起的| 吃什么水果对身体好| 胃气虚吃什么中成药| 百度
Skip to content

面试官:说说你对发布订阅、观察者模式的理解?区别??#295

@huihuiha

Description

@huihuiha

一、观察者模式

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

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

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

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

实现代码如下:

被观察者模式

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就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)

参考文献

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      安全总监是什么级别 5月14日什么星座 牛油果什么时候吃最好 嗯嗯什么意思 肌酐高说明什么问题
      dn是什么意思 哥哥的女儿叫什么 紫薇花什么季节开花 尿隐血2十是什么原因 狗狗蛋蛋红肿是什么原因
      黄痰是什么原因 梦见别人流血是什么预兆 pst是什么意思 醋坛子是什么意思 自慰是什么
      海笋是什么东西 嘛是什么意思 他克莫司软膏治疗什么 订盟是什么意思 bg是什么意思
      龋齿是什么原因造成的hcv9jop0ns2r.cn 同学过生日送什么礼物好hcv9jop8ns2r.cn 心脏彩超能查出什么hcv9jop1ns1r.cn 杏有什么作用和功效tiangongnft.com moss是什么意思hcv9jop8ns1r.cn
      贾珍和贾政是什么关系hcv7jop6ns4r.cn 榴莲跟什么不能一起吃hcv8jop5ns0r.cn 吃红薯有什么好处hcv7jop6ns1r.cn 肺动脉流的是什么血hcv9jop2ns3r.cn 抠脚大汉什么意思hebeidezhi.com
      宝宝拉黑色大便是什么原因hcv7jop9ns8r.cn 什么叫脂溢性脱发hcv9jop3ns2r.cn 悦五行属性是什么baiqunet.com 性病是什么症状jinxinzhichuang.com 医学上pi是什么意思hcv9jop3ns9r.cn
      天蝎座女生配什么星座xinjiangjialails.com 今年男宝宝取什么名字好hcv9jop5ns0r.cn slf是什么意思hcv8jop7ns9r.cn 导火索是什么意思hcv8jop3ns2r.cn 稽留流产是什么意思jingluanji.com
      百度