关注点
- 代码结构
- 设计思想
代码结构
订阅者是如何存储的?
Version 16.0
订阅者的存储耦合在 EventBus 类当中,存储结构为 SetMultimap,通过 ReentrantReadWriteLock 来保证该容器是线程安全的,通过抽象 SubscriberFindingStrategy(订阅者查询策略)方便后续扩展,当前版本只有一个实现 AnnotatedSubscriberFinder,通过 @Subscribe 标记注解来查找
Version 29.0-jre
订阅者的存储职责转移到 SubscriberRegistry 类中,职责更加清晰,存储结构为 ConcurrentMap<Class<?>, CopyOnWriteArraySet> 通过读写容器来保证线程安全,具体实现通过 @Subscribe 标记注解来查找
事件调度是如何解耦的?
Version 16.0
事件的分发逻辑和 EventBus 是耦合在一块的,事件调度中属于广度调度策略,且该策略不允许改变
Version 29.0-jre
抽象事件 Dispatcher,将调度职责和 EventBus 解耦,具体如何将事件分发到具体的订阅者扩展 Dispatcher 即可,从而在代码结构上更符合开闭原则、职责更加单一
EventBus 复杂度如何降低的?
Version 16.0
订阅者的存储、注销、事件的调度、订阅异常的处理都在 EventBus 这个类中实现,承担的职责比较多
Version 29.0-jre
EventBus 总体职责比较轻,将订阅者存储的职责委派给 SubscriberRegistry、调度的职责委派给 Dispatcher,只提供稳定的 API。
设计思想
在早期版本中,EventBus 职责划分的不是特别明确,实现逻辑比较重,通过后续的重构,无论从命名上、代码结构上都满足一定的可读性和可扩展性,主要用到以下几个设计原则
- 前期实现上,要提供稳定的 API,后续重构不要破坏
- 持续重构,使其职责更加清晰
- 低耦合,通过抽象 Dispatcher,使其具体调度策略不与 EventBus 耦合
- 提取 SubscriberRegistry,订阅者的管理更加集中、可维护性更好
总结
EventBus 的设计思想值得学习,在设计原则上应用的很恰当。