一文弄懂设计模式之观察者模式、发布订阅模式

前言

hello,大家好!我是图图酱,今天就和大家分享一下设计模式里的观察者模式发布订阅模式,很多人对于这两种设计模式的概念可能有点模糊分不清,有的觉得这两种模式其实是一样的。其实这两种确实很类似但是略有区别,下面就通过简单的实现带大家弄懂这两种模式的区别及用法。

观察者&发布订阅

首先通过上图我们可以清楚的看到两者的区别。

  • 观察者模式是通过观察者(Observer)直接对目标(Subject)进行订阅(Subscribe),事件通知也是由目标直接通知观察者,两者直接是直接关联的。
  • 发布订阅模式在观察者模式之前多了一个时间时间调度中心(Event Channel),订阅者(Subscriber)和发布者(Publisher)不是直接关联的,两者直接的消息传递需要经过调度中心来进行,这样的好处就是做到了松散解耦,更为灵活。

Linus Torvalds --- 'Talk is cheap . Show me the code.'

观察者模式

js 复制代码
// 定义一个目标对象
class Subject {
  constructor() {
    this.Observers = [];
  }
  
  add(observer) {
    //添加
    this.Observers.push(observer);
  }
  
  remove(observer) {
    //移除
    this.Observers.filter((item) => item === observer);
  }
  
  notify() {
    //通知所有观察者
    this.Observers.forEach((item) => {
      item.update();
    });
  }
}

//定义观察者对象
class Observer {
  constructor(name) {
    this.name = name;
  }
  
  update() {
    console.log(`my name is:${this.name}`);
  }
}

// 实例化目标对象
let sub = new Subject();

let obs1 = new Observer("observer11");
let obs2 = new Observer("observer22");

sub.add(obs1);
sub.add(obs2);

sub.notify();

观察者模式由目标(Subject)维护对应的观察者对象(Observer),在需要通知时再由目标去通知其维护的观察者对象,主要的调度工作都在观察者这里

发布订阅模式

js 复制代码
// 事件中心
class Events {
  // 订阅者列表
  events = {};

  // 订阅
  subscribe(key, fn) {
    if (!Array.isArray(this.subscriber[key])) {
      this.subscriber[key] = [];
    }
    this.subscriber[key].push(fn);
  }

  // 取消单个订阅
  unsubscribe(key, fn) {
    const subscribers = this.subscriber[key] || [];
    this.subscriber[key] = subscribers.filter((_fn) => _fn !== fn);
  }

  // 取消所有订阅
  unsubscribeAll(key) {
    this.subscriber[key] = [];
  }

  // 发布
  publish(key, ...args) {
    const subscribers = this.subscriber[key] || [];

    if (subscribers.length === 0) {
      console.log("has't subscriber");
    }

    subscribers.forEach((subscriber) => {
      subscriber.apply(this, args);
    });
  }
}

// 创建发布订阅信道中介
const e = new Events();

// 发布者
const publisher = {
  article1: 'article1',
  article2: 'article2',
};

// 订阅者
const subscriber1 = (article) => {
  console.log(`sub1 receive ${article}`);
};
const subscriber2 = (article) => {
  console.log(`sub2 receive ${article}`);
};

// 订阅操作
e.subscribe('event1', subscriber1);
e.subscribe('event1', subscriber2);

// 发布操作
e.publish('event1', publisher.article1);
// sub1 receive article1
// sub2 receive article1

// 多事件发布订阅
e.subscribe('event2', subscriber1);
e.publish('event2', publisher.article1);
// sub1 receive article1

// 取消单个订阅
e.unsubscribe('event1', subscriber1);
e.publish('event1', publisher.article2);
// sub2 receive article2

// 取消所有订阅
e.unsubscribeAll('event1');
e.publish('event1');
//  has't subscriber

发布订阅模式有一个单独的调度中心(Events),它在这里负责了在观察者模式里由观察者(Observer)维护的调度工作,这样订阅者(Subscriber)发布者(Publisher)就变得纯粹,发布者只需要发布事件,订阅者做好接到响应需要的回调。

小结

  1. 可以理解为观察者模式里,目标(Subject)维护了一个观察者(Observer)列表,[obs1, obs2],在发布时通知这个观察者列表里的观察者,发布订阅里,事件中心(Events)维护的是个{event1: [sub1, sub2], event2: [sub1, sub3]}事件对象
  2. 观察者模式由具体目标(Subject)调度,发布订阅模式由调度中心(Events)统一调度,发布订阅模式比观察者模式多一个调度中心
  3. 发布订阅模式中,组件是松散耦合的,观察者模式相反。

ok👌,到这里,大家是不是对于这两种设计模式有了清晰的了解了呢😉,以上是个人对于这两个设计模式的理解,如有错误请多指教🫡

参考

  1. www.patterns.dev/posts/obser...
  2. juejin.cn/post/684490...
  3. juejin.cn/post/727788...
相关推荐
吃土的女孩3 分钟前
开发者的秘密武器:用MemFire Cloud快速上线项目
前端·javascript·后端
crazy的蓝色梦想10 分钟前
【超详细】React SSR 服务端渲染实战
前端·javascript·react.js
心.c11 分钟前
Vue2
前端·javascript·vue.js
蜗牛_snail14 分钟前
Ant Design Vue 之可拖拽对话框
前端·javascript·vue.js
闲人陈二狗19 分钟前
在vue3中如何使用图标库fontawesome
开发语言·javascript·ecmascript
好像是个likun34 分钟前
Echarts的认识和基本用法
前端·javascript·echarts
时间sk1 小时前
HTML——73.button按钮
前端·javascript·html
一 乐2 小时前
校园台球|基于SprinBoot+vue的校园台球厅人员与设备管理系统(源码+数据库+文档)
前端·javascript·数据库·vue.js·spring boot·校园台球
余道各努力,千里自同风4 小时前
Js中的Object.entries()
开发语言·前端·javascript
喵王叭5 小时前
【测试工具】 Postman 基本使用
javascript·测试工具·postman