前段时间,小名同学review原有系统时,提出我们的系统应该引入用于级联更新的机制。说白了,就是发布订阅模式的应用。当时技术评估结论是暂时不需要,但是如果需要实现应该怎么实现呢?后来,我在阅读代码&文档时,发现一个很好的模型可以用来实现上述逻辑。
先说说应用场景。
在写应用系统时,经常会有这样的场景:
- 更新订单时,需要将这样的变更通知到供应商&商家&卖家。
- 子类目发生变动时,让父类目感知,或者是父父类目感知。
- 某一事件触发发送不同类型的通知邮件。
- 规则变更产生的一系列级联的操作。
…
槽糕的实现
如果说只是通知,采用同步&异步调用的方式,也可以满足上述功能。
弊端
- 完全面向过程的思考方式,这样的写法会产生又长又软的面条式代码。
- 扩展性较差,调用的方式容易将代码写乱,同一类操作格式不统一(毕竟是多人并行开发)。而且如果是异步的话,在主流程里各自需要有起线程的代码。
- 耦合性强,“通知”这种类消息的做法,其步骤往往不应该在主流程主要步骤里。
- 可读性较差。
有没有什么可以避免上述弊端的解决方案呢?
答案肯定是有的。
首先映入我脑海的就是设计模式中的发布-订阅模式,但是这样需要实现一整套代码逻辑,定义一堆类。虽然能实现,但是方便吗?no。
searching… let me see
EventBus -> https://github.com/greenrobot/EventBus
EventBus is a publish/subscribe event bus for Android and Java.
简单、高效、体积小。
另外,事件总线EventBus的实现,从DDD的角度来说,以事件的弱引用方式对我们的模块和领域边界有很好的解耦作用。**
科普:
Publisher发布者:用于分发我们的Event事件,在EventBus中通过post方法进行分发传送。
Subscriber订阅者:用于接受我们的事件,我们在订阅事件中处理我们接收的数据。
Event事件:任何一个对象都可以作为事件,比如任何字符串,事件是发布者和订阅者之间的通信载体。
EventBus:类似于中转站,将我们的事件进行对应的分发处理。
按照我的理解,示意图如下:
具体代码的简单实现
EventBus in 3 steps( copied from github)
1.Define events:
1 | public static class MessageEvent { /* Additional fields if needed */ } |
2.Prepare subscribers: Declare and annotate your subscribing method, optionally specify a thread mode:
1 | (threadMode = ThreadMode.MAIN) |
Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle:
1 |
|
3.Post events:
1 | EventBus.getDefault().post(new MessageEvent()) |
具体进一步如何实现,可以参考官网:
http://greenrobot.org/eventbus/documentation/how-to-get-started/
from my point:
step1. 定义Event基础类(implements Serializable),在Event中定义EventBus。同时,定义成异步的事件总线 和 异常处理。
1 | public static final EventBus TEST_BUS = new AsyncEventBus( |
step2. 定义用于传输的ConcreteEvent类。该类extends Event。有自己的属性信息。
step3. 定义订阅类
在订阅类初始化的时候,Event.TEST_BUS.register(this);
在订阅类的方法上配置 @Subscribe
同时,配置@AllowConcurrentEvents,用于线程安全。
1
2
3
4
5@Subscribe
@AllowConcurrentEvents
public void testSubscribe(@NonNull ConcreteEvent event){
// TODO 订阅方处理自己的逻辑
}
参考&致谢
- https://github.com/greenrobot/EventBus
- https://www.jianshu.com/p/f9ae5691e1bb
- https://www.jianshu.com/p/c35f0c545fc9