目录与学习目标
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-pattern
Git下载地址:
https://github.com.cnpmjs.org/hesuijin/hesujin-design-pattern.git
demo-study模块 下 behavior_design_pattern observer包