Java设计替代if-else和instanceof

时间:2016-09-11 22:16:46

标签: java json architecture software-design instanceof

我们的Java应用程序在后端使用Google Guava EventBus进行通信。其中一些事件使用泽西岛的server-sent events support发送到客户端以启用通知。客户端仅对某些类型的事件感兴趣,并且这些事件以JSON格式发送到客户端。

目前,我们正在使用if-elseinstanceof来处理巨型方法中的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() {

   }
}

这是我能想到的最合理的方法。

需要建议和想法。

1 个答案:

答案 0 :(得分:0)

我相信Google Guava EventBus是精确设计的,所以你不必用很多if-else-if来定义这样的方法:

  

有些人为EventBus提出了一个通用的Handler接口   听众。这会遇到Java使用类型擦除的问题,而不是   提到可用性方面的问题。

     

...

     

由于擦除,没有一个类可以使用不同的类型参数多次实现通用接口。这是传统Java事件的一大步,即使actionPerformed和keyPressed不是非常有意义的名称,至少你可以实现这两种方法!

通过创建自己的标记,您将重新创建他们试图避免的问题。

对我来说,这就是Guava建议使用它的方式:

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/