目录与学习目标
1:EventBus 框架功能需求介绍2:EventBus里面应该有什么 3:跟经典的观察者模式的区别4:@Subscribe 注解5:具体流程6:相关类
1:EventBus 框架功能需求介绍
EventBus 翻译为“事件总线”,它提供了实现观察者模式的骨架代码。我们可以基于此框架,非常容易地在自己的业务场景中实现观察者模式,不需要从零开始开发。 其中,Google Guava EventBus 就是一个比较著名的 EventBus 框架,它不仅仅支持异步非阻塞模式,同时也支持同步阻塞模式作用:隐藏实现细节,降低开发难度,做到代码复用,解耦业务与非业务代码
2:EventBus里面应该有什么
1:通过构造方法 生成EventBus()区分同步阻塞 异步非阻塞同步阻塞:EventBus() 异步非阻塞:EventBus(Executor executor)2:register() 函数EventBus 类提供了 register() 函数用来注册观察者3:unregister() 函数unregister() 函数用来从 EventBus 中删除某个观察者4:post() 函数EventBus 类提供了 post() 函数,用来给观察者发送消息
3:跟经典的观察者模式的区别
经典的观察者模式是把消息发送给所有的观察者(只要注册 不管 发送的消息事件 是否匹配)EventBus:当我们调用 post() 函数发送消息的时候,并非把消息发送给所有的观察者,而是发送给 消息事件可匹配的 观察者; 注意: 1:消息事件可匹配(event) 2:观察者(已经注册)能接收的消息类型是发送消息(post 函数定义中的 event)类型的父类不仅会给发送的消息给对应的观察者,还会把该消息同样发送给持有该消息类型的父类的观察者ChildObserver 能接收的消息类型是 CMsg,Parentbserver 能接收的消息类型是 PMsg ,MyObserver 能接收的消息类型是 MMsg。其中Parentserver是ChildObserver的父类当发布者发送 CMsg类型的消息 ChildObserver Parentbserver 都能收到当发布者发送 PMsg类型的消息 Parentbserver 能够收到当发布者发送 MMsg类型的消息 MyObserver 能够收到
EventBus 通过 @Subscribe 注解来标明,某个函数能接收哪种类型的消息当通过 register() 函数将 MyObserver 类对象注册到 EventBus 的时候,EventBus 会根据 @Subscribe 注解找到 methodOne() 和 methoTwo(),并且将两个函数能接收的消息类型记录下来(MsgOne->methodOne,MsgTwo->methodTwo)。当我们通过 post() 函数发送消息(比如 MsgOne 消息)的时候,EventBus 会通过之前的记录(MsgOne->methodOne),调用相应的函数(methodOne)。
public MyObserver { //...省略其他属性和方法... @Subscribe public void methodOne(MsgOne event) { //... } @Subscribe public void methodTwo(MsgTwo event) { //... } }
5:具体流程

最关键的一个数据结构是 Observer 注册表,记录了消息类型和可接收消息函数的对应关系。当调用 register() 函数注册观察者的时候,EventBus 通过解析 @Subscribe 注解,生成 Observer 注册表。当调用 post() 函数发送消息的时候,EventBus 通过注册表找到相应的可接收消息的函数,然后通过 Java 的反射语法来动态地创建对象、执行函数。对于同步阻塞模式,EventBus 在一个线程内依次执行相应的函数。对于异步非阻塞模式,EventBus 通过一个线程池来执行相应的函数。
6:相关类
1.Subscribe(定义注解 类)2.ObserverRegistry(注册类)3.ObserverAction (提供给注册类使用的反射类)
4.EventBus (调用 ObserverRegistry类方法 ) 同步阻塞:EventBus() 异步非阻塞:EventBus(Executor executor) 注册方法:register 发送方法:post
public class EventBus { private Executor executor; private ObserverRegistry registry = new ObserverRegistry(); /** * MoreExecutors.directExecutor() 是 Google Guava 提供的工具类,看似是多线程,实际上是单线程 * 之所以要这么实现,主要还是为了跟 AsyncEventBus 统一代码逻辑,做到代码复用。 * 构造方法单线程 */ public EventBus() { this(MoreExecutors.directExecutor()); } //与AsyncEventBus的构造方法代码复用 protected EventBus(Executor executor) { this.executor = executor; } /** * @param object */ public void register(Object object) { registry.register(object); } /** * @param objects */ public void registerAllObserver(List<Object> objects) { objects.forEach(object -> registry.register(object)); } public void post(Object event) { List<ObserverAction> observerActions = registry.getMatchedObserverActions(event); for (ObserverAction observerAction : observerActions) { executor.execute(() -> observerAction.execute(event)); } }}
5.AsyncEventBus(继承EventBus类)
//为了实现异步非阻塞的观察者模式,它就不能再继续使用 MoreExecutors.directExecutor() 了,public class AsyncEventBus extends EventBus { public AsyncEventBus(Executor executor) { super(executor); }}
项目连接
请配合项目代码食用效果更佳:项目地址:https://github.com/hesuijin/hesujin-design-patternGit下载地址:https://github.com.cnpmjs.org/hesuijin/hesujin-design-pattern.gitdemo-study模块 下 behavior_design_pattern observer包