设计模式-发布订阅

chalmery Lv2

发布订阅

观察者模式(Observer Pattern),或者叫发布订阅,是一种行为型设计模式,它定义了一种一对多的依赖关系,使得多个观察者对象可以同时监听和被通知被观察者对象的状态变化。

观察者模式的主要特点如下:

  1. 主题和观察者的解耦:观察者模式通过定义抽象主题(Subject)和抽象观察者(Observer)来实现主题和观察者的解耦。主题对象并不直接依赖于具体的观察者,而是依赖于观察者的抽象。这样可以使主题对象和具体观察者对象相互独立,彼此之间的耦合度降低。
  2. 一对多的依赖关系:观察者模式中,一个主题对象可以有多个观察者对象订阅并监听它的状态变化。当主题对象的状态发生变化时,所有依赖于它的观察者对象都会收到相应的通知并进行相应的处理。这种一对多的依赖关系使得我们可以方便地增加或删除观察者对象,而不需要修改主题对象的代码。
  3. 松散耦合的设计:观察者模式通过松散耦合的设计,使得主题对象和观察者对象之间的依赖关系变得松散。主题对象只需要知道观察者对象实现了特定的观察者接口,而不需要了解具体的观察者对象。这样可以使得系统更加灵活,易于扩展和维护。
  4. 发布-订阅机制:观察者模式可以看作是一种发布-订阅(Publish-Subscribe)机制的实现。主题对象充当发布者,观察者对象充当订阅者。主题对象维护着一组观察者对象,并在状态变化时主动通知观察者对象,从而实现发布-订阅的通信机制。

观察者模式在实际应用中非常常见,例如事件驱动编程、GUI开发、消息队列等。它可以帮助我们实现对象之间的松散耦合,提高系统的可维护性、扩展性和灵活性。

概念

发布订阅核心就是一个Map或者数组之类的容器,存储所有注册的事件,以及对应的回调。而具体每件事情完成后,告诉事件中心,我要触发某个事件的回调,事件中心从容器中找到对应的事件,然后执行函数。可以发现整体是解耦的状态,事件触发者,和事件的函数是分离的,通过中间者eventManager来沟通。

框架的使用

上述概念有没有很熟悉,这个和后端常用中间件MQ,桌面框架electron中的一些地方很像?其实这些地方都用到了这个设计模式。

  • 在我们使用消息队列,无论是rabbitMq还是RocketMq的时候,都是一样的,我们往指定的topic中发送消息,然后监听这个topic的消息,然后处理,和上述图的结构一样,本质就是一个发布订阅的设计模式。
  • electron框架中通过ipcRenderer来管理事件,send来触发事件,on来注册遇到这个事件要做什么事情
1
2
3
4
//触发事件
electron.ipcRenderer.send('eventName', data);
//注册事件的处理动作
electron.ipcRenderer.send('eventName', func);

日常开发如何使用

1 在前端开发中使用

在前端开发中,我们会发现组件传值在某些情况异常复杂,甚至无法做到,我们会发现,常见的就是父子传值,如果是两个没有嵌套关系的组件传值呢?貌似很复杂,常常可能就会用一个中介来做这件事,比如:redux,vuex之类的状态管理,这边存,那边取。其实可以直接运用这个设计模式来做到。

代码参考:发布订阅

2 在后端开发中使用

在后端开发中,我们常见的一个业务场景就是,做了一件事之后,要做一些事情,比如:

  • 要发mq
  • 要发通知
  • 要存es
  • 要刷新缓存

这些事情常常是异步的,和这件事情没有关系,开发中常常会开启一个线程池,或者发一个mq异步里去处理。这样当然是可以的但是有这些缺点:

  • 整体不够抽象化,没有把这类事情做一个抽象,代码不够规范化。
  • 有些时候要做的事情,比如要发mq,要存es等,没有前后顺序,也就是这些事件是互不干扰的,可以在不同的线程处理,而mq通常创建一个监听后,顺序的去做这些事情,只发挥了一个线程的作用

代码参考:发布订阅

像上述代码示例的内容,在下面Add 事件发布的时候,EventManager就会依次开启线程来调用监听。SendMqEventListener,SendSlsEventListener会分两个线程来执行

1
2
3
4
5
6
7
8
public class BusinessCode {
public static void main(String[] args) {
//省略业务代码
//做完事情之后,发送通知
AddEntity entity = new AddEntity("name","code","desc");
EventManager.publish(EventEnum.ADD,entity);
}
}
  • 标题: 设计模式-发布订阅
  • 作者: chalmery
  • 创建于 : 2023-07-14 00:00:00
  • 更新于 : 2023-07-14 00:00:00
  • 链接: https://github.com/chalmery/1698904213/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论