手写EventBus(观察者模式、源码阅读、反射)

学习王争老师《设计模式之美》,观察者模式部分实现了一个简单的EventBus,太棒了,设计特别巧妙,其中的解耦思路,运用在自己正在开发的项目中,大大优化原本不好维护的代码。在此记录下,方便回顾与学习。

整个小框架的代码实现包括5个类:
EventBus、AsyncEventBus、Subscribe、ObserverAction、ObserverRegistry。

1. Suscibe

Subscribe 是一个注解,用于标明观察者中的哪个函数可以接收消息。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Beta
public @interface Subscribe {
}

2. ObserverAction

ObserverAction 类用来表示 @Subscribe 注解的方法,其中,target 表示观察者类,method 表示方法。它主要用在 ObserverRegistry 观察者注册表中。

/**
 * ObserverAction用来表示@Subscribe注解的方法.
 * 

* target表示观察者类,method表示方法。 * */ public class ObserverAction { private Object target; private Method method; public ObserverAction(Object target, Method method) { this.target = target; this.method = method; } public void execute(Object event) { // event 是 method方法的参数 try { method.invoke(target, event); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }

3. ObserverRegister

ObserverRegistry 类就是前面讲到的 Observer 注册表,是最复杂的一个类,框架中几乎所有的核心逻辑都在这个类中

public class ObserverRegistry {
    private ConcurrentMap, CopyOnWriteArraySet> registry = new ConcurrentHashMap<>();

    public void register(Object observer) {
        Map, Collection> observerAction = findAllObserverAction(observer);
        for (Map.Entry, Collection> entry : observerAction.entrySet()) {
            Class eventType = entry.getKey();
            Collection eventActions = entry.getValue();
            CopyOnWriteArraySet observerActions = registry.computeIfAbsent(eventType,
                    e -> new CopyOnWriteArraySet());
            observerActions.addAll(eventActions);
        }
    }

    public List getMatchedObserverActions(Object event) {
        List matchedObservers = new ArrayList<>();
        Class postedEventType = event.getClass();
        for (Map.Entry, CopyOnWriteArraySet> entry : registry.entrySet()) {
            Class eventType = entry.getKey();
            if (eventType.isAssignableFrom(postedEventType)) {
                matchedObservers.addAll(entry.getValue());
            }
        }
        return matchedObservers;
    }

    private Map, Collection> findAllObserverAction(Object observer) {
        Map, Collection> observerActions = new HashMap<>();
        Class clazz = observer.getClass();
        for (Method method : getAnnotateMethods(clazz)) {
            Class[] parameterTypes = method.getParameterTypes();
            Class eventType = parameterTypes[0];
            if (!observerActions.containsKey(eventType)) {
                observerActions.put(eventType, new ArrayList<>());
            }
            observerActions.get(eventType).add(new ObserverAction(observer, method));
        }
        return observerActions;
    }

    private List getAnnotateMethods(Class clazz) {
        List annotatedMethods = new ArrayList<>();
        for (Method method : clazz.getDeclaredMethods()) {
            if (method.isAnnotationPresent(Subscribe.class)) {
                Class[] parameterTypes = method.getParameterTypes();
                Preconditions.checkArgument(parameterTypes.length == 1,
                        "Method %s has @Subscribe annotation but has %s parameters." + "Subscriber methods must have exactly 1 parameter.",
                        method, parameterTypes.length);
                annotatedMethods.add(method);
            }
        }
        return annotatedMethods;
    }
}

4. EventBus

public class EventBus {
    private Executor executor;
    private ObserverRegistry registry = new ObserverRegistry();

    public EventBus() {
        this(MoreExecutors.directExecutor());
    }

    protected EventBus(Executor executor) {
        this.executor = executor;
    }

    public void register(Object object) {
        registry.register(object);
    }

    public void post(Object event) {
        List observerActions = registry.getMatchedObserverActions(event);
        for (ObserverAction observerAction : observerActions) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    observerAction.execute(event);
                }
            });
        }
    }
}

5. AsyncEventBus

public class AsyncEventBus extends EventBus {

    public AsyncEventBus(Executor executor) {
        super(executor);
    }
}

演示Demo

public class DemoUserService {

    private EventBus eventBus;

    public DemoUserService() {
        eventBus = new EventBus();
    }

    /**
     * 添加观察者.
     *
     * @param observers
     */
    public void setRegObservers(List observers) {
        for (Object observer : observers) {
            eventBus.register(observer);
        }
    }

    /**
     * 注册用户,触发动作。
     * @param phone
     * @param password
     */
    public Long register(String phone, String password) {
        // 注册用户。。。
        Long userId = 1L; // 注册返回用户id

        eventBus.post(userId);

        return userId;
    }
}
 

                            
                        
                    
                    
                    

你可能感兴趣的:(手写EventBus(观察者模式、源码阅读、反射))