编写不易,转载请注明(http://shihlei.iteye.com/blog/2426888)!
一 概述
最近看RxJava,其骨架就是使用的观察者模式,所以对观察者模式做个总结,顺便记录一下Guava EventBus的实现(事件监听,其实也相当于观察者模式)
二 观察者模式
1)概述
观察者模式:行为模式,提供一种一对多关系绑定对象的方法,一个对象状态需发生改变,绑定对象能收到通知完成自己的业务更新。
主要成员:
被观察者(Observerable):状态变化,通知所有的观察者。
观察者(observer):接收到“被观察者”的状态变化通知,执行自己的业务。
使用场景:
“被观察者”的状态变化需要通知多个“观察者”,但“被观察者”不需要知道观察者的个数具体细节,他们之间互相独立。一般“观察者”之间相互独立,不会彼此影响。
2)Demo
package x.rx.observer; import java.util.LinkedList; import java.util.List; /** * 观察者模式: * 1)被观察者(Observerable):维护一个观察者队列,事件产生时,回调所以的观察者 * 2)观察者(Observer):注册到"被观察者"中,接收通知,执行自己的业务 * * @author shilei */ public class ObserverPatternDemo { public static void main(String[] args) { Observerable observerable = new Observerable(); observerable.register(() -> { System.out.println("observer1 handle finish!"); }).register(() -> { System.out.println("observer2 handle finish!"); }); observerable.generateEvent(); } /** * 观察者 */ interface Observer { void doEvent(); } /** * 被观察者 */ static class Observerable { private ListobserverList = new LinkedList<>(); /** * 注册观察者 * * @param observer 观察者 */ Observerable register(Observer observer) { observerList.add(observer); return this; } /** * 取消注册 */ Observerable unRegister(Observer observer) { observerList.remove(observer); return this; } /** * 产生事件 */ void generateEvent() { for (Observer observer : observerList) { observer.doEvent(); } } } }
三 Guava EventBus
1) 概述
Guava EventBus 实现了事件监听器模式,主要提供一套基于注解的事件总线,可以灵活的使用。
使用方式:
1)定义一个关注的Event
2)定义一个监听处理方法,@Subscribe 标记,里面实现业务逻辑
3)注册到EventBus即可
2)Demo
(1)依赖
com.google.guava guava 23.0
(2)代码
package x.rx.eventbus; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; /** * guava eventbus * * @author shilei */ public class EventBusDemo { public static void main(String[] args) { EventBus eventBus = new EventBus("demo"); // 注册 eventBus.register(new EventListener()); // 产生事件 eventBus.post(new Event()); } /** * 事件 */ static class Event { } /** * 事件监听器 */ static class EventListener { @Subscribe //这里标记这个方法是事件处理方法 public void handle1(Event event) { System.out.println("handle1 finish! "); } @Subscribe public void handle2(Event event) { System.out.println("handle2 finish! "); } } }
3)源码分析
(1)事件注册到总线:EventBus的register()
private final SubscriberRegistry subscribers = new SubscriberRegistry(this); /** * Registers all subscriber methods on {@code object} to receive events. * * @param object object whose subscriber methods should be registered. */ public void register(Object object) { subscribers.register(object); }
“被观察者”的核心,提供一个队列,维护所有需要通知的观察者,Guava EventBus 这个工作代理给了 SubscriberRegistry , SubscriberRegistry 提供任何类型的事件到事件处理类的绑定关系。
看看注册的细节:
/** * All registered subscribers, indexed by event type. * *The {@link CopyOnWriteArraySet} values make it easy and relatively lightweight to get an * immutable snapshot of all current subscribers to an event without any locking. */ private final ConcurrentMap
, CopyOnWriteArraySet > subscribers = Maps.newConcurrentMap(); /** * Registers all subscriber methods on the given listener object. */ void register(Object listener) { Multimap , Subscriber> listenerMethods = findAllSubscribers(listener); for (Map.Entry , Collection > entry : listenerMethods.asMap().entrySet()) { Class> eventType = entry.getKey(); Collection eventMethodsInListener = entry.getValue(); CopyOnWriteArraySet eventSubscribers = subscribers.get(eventType); if (eventSubscribers == null) { CopyOnWriteArraySet newSet = new CopyOnWriteArraySet (); eventSubscribers = MoreObjects.firstNonNull(subscribers.putIfAbsent(eventType, newSet), newSet); } eventSubscribers.addAll(eventMethodsInListener); } }
内部是一个ConcrurentMap,key 是事件class,value是个 CopyOnWriteArraySet
看看findAllSubscribers(listener) 的细节:
/** * Returns all subscribers for the given listener grouped by the type of event they subscribe to. */ private Multimap, Subscriber> findAllSubscribers(Object listener) { Multimap , Subscriber> methodsInListener = HashMultimap.create(); Class> clazz = listener.getClass(); for (Method method : getAnnotatedMethods(clazz)) { Class>[] parameterTypes = method.getParameterTypes(); Class> eventType = parameterTypes[0]; methodsInListener.put(eventType, Subscriber.create(bus, listener, method)); } return methodsInListener; }