我们的Java应用程序在后端使用Google Guava EventBus进行通信。其中一些事件使用泽西岛的server-sent events support发送到客户端以启用通知。客户端仅对某些类型的事件感兴趣,并且这些事件以JSON格式发送到客户端。
目前,我们正在使用if-else
和instanceof
来处理巨型方法中的JSON正文生成。 UIEvent
只是一个用作过滤器的标记界面。
@Subscribe
public void handleEvent(final UIEvent event) {
if (event instanceof A) {
A a = (A) event;
} else if (event instance B) {
B b = (B) event;
} ...
}
当越来越多的事件被添加到系统时,此代码开始变得混乱。经过一些研究,有一些替代方案,但还不够好。
1)思考。
使用反射意味着我们可以使用声明方式从事件对象中检索数据,而无需知道确切的类型。但是使用反射不是类型安全的,并且在处理嵌套路径时可能会很麻烦,例如: a.b.c
。
2)多态性
多态性看起来是instanceof
的一个很好的替代品,但在这种情况下确实有效。使用多态意味着将toJSON
方法添加到UIEvent
接口。但这会恢复依赖关系流并将UI细节暴露给事件总线。
3)包装类
我还考虑使用事件包装器类将JSON主体构建逻辑封装在不同的类中。然后在事件总线的handleEvent
方法中,我可以获取事件对象的类型并使用命名约定找到包装类,然后构造包装类实例,调用toJson
方法来获取JSON体。
public class AWrapper {
public AWrapper(A a) {
}
public Object toJson() {
}
}
这是我能想到的最合理的方法。
需要建议和想法。
答案 0 :(得分:0)
我相信Google Guava EventBus是精确设计的,所以你不必用很多if-else-if来定义这样的方法:
有些人为EventBus提出了一个通用的Handler接口 听众。这会遇到Java使用类型擦除的问题,而不是 提到可用性方面的问题。
...
由于擦除,没有一个类可以使用不同的类型参数多次实现通用接口。这是传统Java事件的一大步,即使actionPerformed和keyPressed不是非常有意义的名称,至少你可以实现这两种方法!
通过创建自己的标记,您将重新创建他们试图避免的问题。
EventBus eventBus = new EventBus();
eventBus.register(new Object(){
@Subscribe
public void handleEvent(A a) {
System.out.println("a");
}
});
eventBus.register(new Object(){
@Subscribe
public void handleEvent(B b) {
System.out.println("b");
}
});
...
eventBus.post(new A());
eventBus.post(new B());
每个事件类型一个处理程序方法。 显然,订阅者不需要像本例中的匿名类。
http://tomaszdziurko.pl/2012/01/google-guava-eventbus-easy-elegant-publisher-subscriber-cases/