「设计模式」观察者模式

「设计模式」观察者模式

首页冒险解谜观察者系统重复更新时间:2024-05-07
前言

观察者模式归属于行为型设计模式,而行为型设计模式主要解决的是“类或对象之间的交互问题”。

观察者模式也被称为发布订阅者模式。

在 GoF 的《设计模式》一书中,它的定义是这样的:

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

翻译成中文即为:在对象间定义了一个一对多的依赖,但这个对象改变状态的时候,所有它的依赖者都会收到通知,并自动更新。

一般情况下,被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者(Observer)。但也有其他的叫法,比如:Subject-Observer、Publisher-Subscriber、Producer-Consumer、EventEmitter-EventListener、Dispatcher-Listener。

根据应用场景的不同,观察者模式会有不同的代码实现方式:

  1. 同步阻塞的、异步非阻塞的
  2. 进程内的实现方式、跨进程的实现方式
  3. ....
同步阻塞的观察者模式被观察者

被观察者,或者可以称为事件的发送者。

根据定义,可以比较容易得出被观察者要做的事情:

  1. 注册/添加 观察者
  2. 当事件发生时,通知观察者
  3. 有添加就有删除,所以还应该有一个删除观察者

interface Subject{ void registerObserver(Observer observer); void notifyObserver(Data data); void removeObserver(Observer observer); } class SubjectImpl implements Subject{ private List<Observer> observers=new ArrayList<>(); @Override public void registerObserver(Observer observer) { observers.add(observer); } @Override public void notifyObserver(Data data) { for(Observer observer:observers){ observer.update(data); } } @Override public void removeObserver(Observer observer) { observers.remove(observer); } }观察者

观察者,或者可以称为事件的接收者。

当对应事件变更的时候,会收到通知并进行自动更新

interface Observer{ void update(Data data); } class ObserverImpl_1 implements Observer{ @Override public void update(Data data) { System.out.println("ObserverImpl_1,收到***" data.getData()); } } class ObserverImpl_2 implements Observer{ @Override public void update(Data data) { System.out.println("ObserverImpl_2,收到***" data.getData()); } }传递的数据/信息

class Data{ private String data; Data(){ } Data(String str){ this.data=str; } public String getData() { return data; } public void setData(String data) { this.data = data; } }测试/示例

public class Demo { public static void main(String[] args) { Observer observer_1 = new ObserverImpl_1(); // 观察者1号 Observer observer_2 = new ObserverImpl_2(); // 观察者2号 Subject subject = new SubjectImpl(); // 被观察者 subject.registerObserver(observer_1); subject.registerObserver(observer_2); subject.notifyObserver(new Data("数据已发送变更")); } }异步非阻塞的观察者模式

如果只是做一个简单的实现,不考虑通用性、扩展性什么的,那么只需要在上述同步阻塞的观察者模式下,做些许的改动即可。有两种方案可以实现。

  1. 在Observer#update(...)方法中创建一个线程异步的去执行更新逻辑。
  2. 在调用被观察者的notifyObserver(...)方法时,创建一个线程池,异步的去执行Observer#update(...)方法。

分析:

第一种方法会使得线程创建的数量不可控,而且过多的线程创建和销毁势必会导致性能问题。

第二种方法虽然通过线程池使得线程的数量和创建、销毁可控了。但是问题在于,其把线程池的创建、调用等逻辑耦合在了被观察者。如果项目想要复用这个异步非阻塞的观察者模式,那么势必又要在新的被观察者里添加线程池、调用线程池【重复操作】。

EventBus 框架

EventBus 翻译为“事件总线”,它提供了实现观察者模式的骨架代码。基于此框架,我们可以非常容易地在自己的业务场景中实现观察者模式,不需要从零开始开发。

其中,Google Guava EventBus 就是一个比较著名的 EventBus 框架,它不仅仅支持异步非阻塞模式,同时也支持同步阻塞模式

Google Guava EventBus的github地址:https://github.com/google/guava

我自己造的轮子已经写到了个人的gitee上:https://gitee.com/shuashua-world/shuashua-blog/tree/master/造轮子/设计模式/观察者模式/EventBus/src/main/java/world/shuashua

这个轮子目前还不支持构造带有泛型参数的观察者方法,不然会出错

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved