EventBus系列文章:
EventBus—使用实践
EventBus—源码解析
EventBus是基于发布订阅者模式的消息处理框架。
EventBus is an open-source library for Android and Java using the publisher/subscriber pattern for loose coupling.
在EventBus的学习当中,发现发布订阅者模式与观察者模式有极大相似之处,而且部分博客将两者等同起来。其实两者是存在差异。两者差异在于调度方式不同。
首先必须知道,发布订阅者模式和观察者模式都是处理对象间一对多关系的行为设计模式,当一个对象状态发生了变化,依赖它的对象都会收到变化和更新。先看看两者的实现方式,然后从中找到两者的不同点,从本质上了解订阅者和观察者模式。
观察者模式有以上两种实现:一种将被观察者方法抽象出来,一种直接创建被观察者对象,两者只是将观察者逻辑抽象出来而已,并没有很大的不同之处。以图一讲述观察者模式,其包含四个角色:
public interface Observerable {
void regiseted(Observer observer);
void unregiseted(Observer observer);
void notifyObserver();
}
public class ConcreteObserverable implements Observerable{
private ArrayList mObservers = new ArrayList<>();
@Override
public void regiseted(Observer observer) {
mObservers.add(observer);
}
@Override
public void unregiseted(Observer observer) {
if (mObservers.contains(observer)) {
mObservers.remove(observer);
}
}
@Override
public void notifyObserver() {
for (Observer observer : mObservers) {
observer.update();
}
}
public void updateState(){
Log.i("wuzl", "update state , the state has changed.");
notifyObserver();
}
}
public interface Observer {
void update();
}
public class ObserverA implements Observer {
@Override
public void update() {
Log.i("wuzl", "Observer A receives the update event");
}
}
public class ObserverB implements Observer {
@Override
public void update() {
Log.i("wuzl", "Observer B receives the update event");
}
}
public class ObserverC implements Observer {
@Override
public void update() {
Log.i("wuzl", "Observer C receives the update event");
}
}
public void verifyObserverPattern(){
Observer observerA = new ObserverA();
Observer observerB = new ObserverB();
Observer observerC = new ObserverC();
ConcreteObserverable observerable = new ConcreteObserverable();
observerable.regiseted(observerA);
observerable.regiseted(observerB);
observerable.regiseted(observerC);
observerable.updateState();
}
wuzl: update state , the state has changed.
wuzl: Observer A receives the update event
wuzl: Observer B receives the update event
wuzl: Observer C receives the update event
(以上代码均为测试验证代码,非实际开发代码)
观察者模式很好地解耦对象间一对多的关系,并且建立起一套触发更新的机制。但是通过上面的例子发现,被观察者(ConcreteObserverable)的对象太重了,既要维护观察者的列表,又要处理消息通知(既当爹又当妈),这违背设计模式中单一职责模式,一旦业务逻辑复杂起来将会酿成灾难呀。同时如果有多个被观察者类(ConcreteObserverable),每个被观察者触发更新逻辑基本一致,重复实现造成大量冗余的垃圾代码。
那么发布订阅者模式应运而生,将观察者的维护、消息处理逻辑剥离出来构建一个调用中心,通过构建事件触发观察者的更新。
讲述发布订阅者模式前,先看看EventBus官网的结构图:
其结构图就是发布订阅者模式的结构图。
public class Dispatcher {
private static Dispatcher mInstance;
private Dispatcher(){}
public static Dispatcher getInstance(){
if (mInstance == null) {
synchronized (Dispatcher.class) {
if (mInstance == null) {
mInstance = new Dispatcher();
}
}
}
return mInstance;
}
private HashMap, List> subscriptionByEventType = new HashMap, List>();
private HashMap>> typesBySubscriber = new HashMap>>();
public void registered(Subscriber subscriber, Class event) {
List subscribers;
if (!subscriptionByEventType.containsKey(event)) {
subscribers = new ArrayList();
} else {
subscribers = subscriptionByEventType.get(event);
}
subscribers.add(subscriber);
subscriptionByEventType.put(event, subscribers);
}
public void unregistered(Subscriber subscriber) {
List> classes = typesBySubscriber.get(subscriber);
if (classes == null) {
return;
}
for (Class event : classes) {
if (subscriptionByEventType.containsKey(event)) {
subscriptionByEventType.remove(event);
}
}
}
public void post(Class event) {
List subscribers = subscriptionByEventType.get(event);
if (subscribers != null && !subscribers.isEmpty()) {
for (Subscriber subscriber : subscribers) {
subscriber.onEvent();
}
}
}
}
public interface Subscriber {
void onEvent();
}
public class SubscriberA implements Subscriber {
@Override
public void onEvent() {
Log.i("wuzl", "SubscriberA onEvent");
}
}
public class SubscriberB implements Subscriber {
@Override
public void onEvent() {
Log.i("wuzl", "SubscriberB onEvent");
}
}
public class SubscriberC implements Subscriber {
@Override
public void onEvent() {
Log.i("wuzl", "SubscriberC onEvent");
}
}
public class Publisher {
public void publishNewEvent(){
Log.i("wuzl", "publishNewEvent");
Dispatcher.getInstance().post(NewEvent.class);
}
public void verifyPublisherPattern(){
Subscriber subscriberA = new SubscriberA();
Subscriber subscriberB = new SubscriberB();
Subscriber subscriberC = new SubscriberC();
Dispatcher.getInstance().registered(subscriberA, NewEvent.class);
Dispatcher.getInstance().registered(subscriberB, NewEvent.class);
Dispatcher.getInstance().registered(subscriberC, NewEvent.class);
publishNewEvent();
}
}
public class NewEvent {
}
wuzl: publishNewEvent
wuzl:SubscriberA onEvent
wuzl:SubscriberB onEvent
wuzl:SubscriberC onEvent
我大大简化了发布订阅者模式的代码,方便例子输出,EventBus中的实现更加的人性化与解耦性更好,详情可查看EventBus—源码解析。
从上面的发布订阅者模式的例子,调度中心维护了观察者事件列表、消息处理逻辑,职责更加单一并且逻辑更加清楚,然后通过事件驱动整个订阅模式的流转。