观察者模式中的角色可以分为Subject和Observer,它们分别为被观察者和观察者,观察者观察被观察者的状态变更。google的guava中提供了EventBus功能,EventBus可以实现观察者模式,下面是一个简单的例子
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 
 | import com.google.common.eventbus.EventBus;import com.google.common.eventbus.Subscribe;
 
 public class TestEventBus {
 
 public static void main(String[] args) {
 EventBus eventBus = new EventBus("test");
 
 eventBus.register(new Listener());
 
 eventBus.post(new Event("hello, world"));
 }
 
 }
 
 class Event {
 public String message;
 
 Event(String message) {
 this.message = message;
 }
 }
 
 class Listener {
 @Subscribe
 public void listen(Event event) {
 System.out.println(event.message);
 }
 }
 
 | 
我们也可以自己实现一个EventBus,虽然在效率上没办法和google的实现相比,但是基本原理都是一样的。
首先我们创建一个用于标记方法是否需要实现订阅的注解
| 12
 3
 4
 
 | @Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)
 public @interface Subscribe {
 }
 
 | 
随后创建EventBus的核心类,其主要功能是添加或移除listener,以及根据传入的参数对符合要求的方法进行调用
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 
 | public class EventBus {
 private Set<Object> listeners = new HashSet<>();
 
 public void register(Object listener) {
 listeners.add(listener);
 }
 
 public void unregister(Object listener) {
 listeners.remove(listener);
 }
 
 
 
 
 
 public void post(Object event) {
 for (Object listener : listeners) {
 Method[] methods = listener.getClass().getDeclaredMethods();
 for (Method method : methods) {
 if (method.isAnnotationPresent(Subscribe.class)) {
 Class[] parameterTypes = method.getParameterTypes();
 if (parameterTypes.length == 1 && parameterTypes[0] == event.getClass()) {
 try {
 
 method.invoke(listener, event);
 } catch (IllegalAccessException | InvocationTargetException e) {
 e.printStackTrace();
 }
 }
 }
 }
 }
 }
 
 }
 
 | 
最后我们对上面的实现进行测试
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | public class Test {
 public static void main(String[] args) {
 EventBus eventBus = new EventBus();
 eventBus.register(new Listener());
 eventBus.post("Mike");
 }
 
 }
 
 class Listener {
 @Subscribe
 public void say(String name) {
 System.out.println("hello, " + name);
 }
 }
 
 | 
测试代码打印出了如下结果
hello, Mike
参考:
https://juejin.im/post/5b61c852e51d451956055476
https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/25
本文链接: https://www.nosuchfield.com/2019/06/24/Observer-mode/