使用instanceof的if-else的Java设计替代方案

使用instanceof的if-else的Java设计替代方案,java,json,architecture,software-design,instanceof,Java,Json,Architecture,Software Design,Instanceof,我们的Java应用程序使用后端进行通信。其中一些事件使用Jersey来发送到客户端以启用通知。客户端只对某些类型的事件感兴趣,这些事件以JSON格式发送到客户端 目前,我们正在使用if-else和instanceof以一种巨大的方法处理JSON正文生成UIEvent只是一个用作过滤器的标记接口 @Subscribe public void handleEvent(final UIEvent event) { if (event instanceof A) { A a = (A) ev

我们的Java应用程序使用后端进行通信。其中一些事件使用Jersey来发送到客户端以启用通知。客户端只对某些类型的事件感兴趣,这些事件以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
的一个很好的替代品,但在这种情况下确实有效。使用多态性意味着向
UIEvent
接口添加类似
toJSON
的方法。但这会还原依赖项流,并向事件总线公开UI详细信息

3) 包装类

我还考虑使用事件包装器类将JSON主体构建逻辑封装在单独的类中。然后在事件总线的
handleEvent
方法中,我可以获取事件对象的类型,并使用命名约定找到包装类,然后构造包装类实例,调用
toJson
方法来获取JSON主体

public class AWrapper {
   public AWrapper(A a) {

   }

   public Object toJson() {

   }
}
这是迄今为止我能想到的最合理的方法

需要建议和想法

我相信它是经过精确设计的,所以您不必用许多if-else-if来定义这种方法:

一些人已经为EventBus提出了一个通用处理程序接口 听众。这与Java使用类型擦除(而不是 提到可用性方面的问题

由于擦除,没有一个类可以使用不同的类型参数多次实现泛型接口。这是传统Java事件的一大倒退,在传统Java事件中,即使actionPerformed和keyPressed不是很有意义的名称,至少您可以实现这两种方法

通过创建您自己的标记,您正在创建他们试图避免的问题

对我来说,番石榴建议这样使用它: 每个事件类型一个处理程序方法显然,订阅者不需要像本例中那样位于匿名类中

其他例子

是这里的标准模式。然而,如果可能的话,你应该试着在事件中测试一个字段并打开它。多态性也有我的投票权。但是在接口上使用类似于
toJson
的方法会使您无法使用json。可以考虑的另一种解决方案是添加一种返回一组通用数据属性的方法(例如,<代码> MAP>代码>),然后将其序列化为JSON。杰克逊或GSON这样的现代库可以毫不费力地将POJOs序列化为JSON,因此您不需要特殊的方法。为什么不创建一个自定义注释来区分内部事件和需要广播到客户端的事件?然后,您可以在
handleEvent()
中使用反射来检查注释是否存在。@markspace我不想使用多态性的原因是,事件类在核心模块中,也被其他模块使用,但JSON逻辑的序列化在API模块中。我不想让核心模块知道API模块。@MickMnemonic发送到客户端的JSON正文有一个预定义的格式,所以简单的JSON序列化是不够的,需要进行数据转换。我以前没有考虑过自定义注释,看起来是区分不同事件的好选择。
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());