目录与学习目标

  1. 1EventBus 框架功能需求介绍
  2. 2EventBus里面应该有什么
  3. 3:跟经典的观察者模式的区别
  4. 4@Subscribe 注解
  5. 5:具体流程
  6. 6:相关类

1:EventBus 框架功能需求介绍

  1. EventBus 翻译为“事件总线”,它提供了实现观察者模式的骨架代码。
  2. 我们可以基于此框架,非常容易地在自己的业务场景中实现观察者模式,不需要从零开始开发。
  3. 其中,Google Guava EventBus 就是一个比较著名的 EventBus 框架,它不仅仅支持异步非阻塞模式,同时也支持同步阻塞模式
  4. 作用:
  5. 隐藏实现细节,降低开发难度,做到代码复用,解耦业务与非业务代码

2:EventBus里面应该有什么

  1. 1:通过构造方法 生成EventBus()区分同步阻塞 异步非阻塞
  2. 同步阻塞:EventBus()
  3. 异步非阻塞:EventBus(Executor executor)
  4. 2register() 函数
  5. EventBus 类提供了 register() 函数用来注册观察者
  6. 3unregister() 函数
  7. unregister() 函数用来从 EventBus 中删除某个观察者
  8. 4post() 函数
  9. EventBus 类提供了 post() 函数,用来给观察者发送消息

3:跟经典的观察者模式的区别

  1. 经典的观察者模式是把消息发送给所有的观察者(只要注册 不管 发送的消息事件 是否匹配)
  2. EventBus
  3. 当我们调用 post() 函数发送消息的时候,并非把消息发送给所有的观察者,而是发送给 消息事件可匹配的 观察者;
  4. 注意:
  5. 1:消息事件可匹配(event
  6. 2:观察者(已经注册)
  7. 能接收的消息类型是发送消息(post 函数定义中的 event)类型的父类
  8. 不仅会给发送的消息给对应的观察者,还会把该消息同样发送给持有该消息类型的父类的观察者
  9. ChildObserver 能接收的消息类型是 CMsg
  10. Parentbserver 能接收的消息类型是 PMsg
  11. MyObserver 能接收的消息类型是 MMsg
  12. 其中ParentserverChildObserver的父类
  13. 当发布者发送 CMsg类型的消息 ChildObserver Parentbserver 都能收到
  14. 当发布者发送 PMsg类型的消息 Parentbserver 能够收到
  15. 当发布者发送 MMsg类型的消息 MyObserver 能够收到

4:@Subscribe 注解

  1. EventBus 通过 @Subscribe 注解来标明,某个函数能接收哪种类型的消息
  2. 当通过 register() 函数将 MyObserver 类对象注册到 EventBus 的时候,
  3. EventBus 会根据 @Subscribe 注解找到 methodOne() methoTwo(),
  4. 并且将两个函数能接收的消息类型记录下来(MsgOne->methodOneMsgTwo->methodTwo)。
  5. 当我们通过 post() 函数发送消息(比如 MsgOne 消息)的时候,
  6. EventBus 会通过之前的记录(MsgOne->methodOne),调用相应的函数(methodOne)。
  1. public MyObserver {
  2. //...省略其他属性和方法...
  3. @Subscribe
  4. public void methodOne(MsgOne event) { //... }
  5. @Subscribe
  6. public void methodTwo(MsgTwo event) { //... }
  7. }

5:具体流程

image.png

  1. 最关键的一个数据结构是 Observer 注册表,记录了消息类型和可接收消息函数的对应关系。
  2. 当调用 register() 函数注册观察者的时候,EventBus 通过解析 @Subscribe 注解,生成 Observer 注册表。
  3. 当调用 post() 函数发送消息的时候,EventBus 通过注册表找到相应的可接收消息的函数,然后通过 Java 的反射语法来动态地创建对象、执行函数。
  4. 对于同步阻塞模式,EventBus 在一个线程内依次执行相应的函数。
  5. 对于异步非阻塞模式,EventBus 通过一个线程池来执行相应的函数。

6:相关类

  1. 1.Subscribe(定义注解 类)
  2. 2.ObserverRegistry(注册类)
  3. 3.ObserverAction (提供给注册类使用的反射类)

  1. 4.EventBus (调用 ObserverRegistry类方法
  2. 同步阻塞:EventBus()
  3. 异步非阻塞:EventBus(Executor executor)
  4. 注册方法:register
  5. 发送方法:post
  1. public class EventBus {
  2. private Executor executor;
  3. private ObserverRegistry registry = new ObserverRegistry();
  4. /**
  5. * MoreExecutors.directExecutor() 是 Google Guava 提供的工具类,看似是多线程,实际上是单线程
  6. * 之所以要这么实现,主要还是为了跟 AsyncEventBus 统一代码逻辑,做到代码复用。
  7. * 构造方法单线程
  8. */
  9. public EventBus() {
  10. this(MoreExecutors.directExecutor());
  11. }
  12. //与AsyncEventBus的构造方法代码复用
  13. protected EventBus(Executor executor) {
  14. this.executor = executor;
  15. }
  16. /**
  17. * @param object
  18. */
  19. public void register(Object object) {
  20. registry.register(object);
  21. }
  22. /**
  23. * @param objects
  24. */
  25. public void registerAllObserver(List<Object> objects) {
  26. objects.forEach(object -> registry.register(object));
  27. }
  28. public void post(Object event) {
  29. List<ObserverAction> observerActions = registry.getMatchedObserverActions(event);
  30. for (ObserverAction observerAction : observerActions) {
  31. executor.execute(() -> observerAction.execute(event));
  32. }
  33. }
  34. }
  1. 5.AsyncEventBus(继承EventBus类)
  1. //为了实现异步非阻塞的观察者模式,它就不能再继续使用 MoreExecutors.directExecutor() 了,
  2. public class AsyncEventBus extends EventBus {
  3. public AsyncEventBus(Executor executor) {
  4. super(executor);
  5. }
  6. }

项目连接

  1. 请配合项目代码食用效果更佳:
  2. 项目地址:
  3. https://github.com/hesuijin/hesujin-design-pattern
  4. Git下载地址:
  5. https://github.com.cnpmjs.org/hesuijin/hesujin-design-pattern.git
  6. demo-study模块 behavior_design_pattern observer