有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java事件总线回顾

我现在开始学习GWT事件总线概念。我觉得这个解决方案非常复杂。所以我试图通过自己编写原型来简化它,以了解所有问题

首先,我将写下我对事件总线的理解(这可能是完全错误的)。 我们有这样的活动

public class FooEvent extends GwtEvent<FooHandler> {
    public static Type<FooHandler> TYPE = new Type<FooHandler>(); //as event type integer ID

    //for.. hm.. probably some inner use in Event Bus
    @Override public Type<FooHandler> getAssociatedType() {
        return TYPE;
    }

    //for handling
    @Override protected void dispatch(FooHandler handler) {
        handler.someMethod(this);
    }
}

处理程序接口

public interface FooHandler extends EventHandler {
    void someMethod(FooEvent event);
}

用法

eventBus.addHandler(FooEvent.TYPE, new FooHandler() {
    @Override
    public void someMethod(FooEvent event) {
        //bla-bla
    }
});
eventBus.fireEvent(new FooEvent());

就这样。现在是我的原型

//replaced GwtEvent
interface UniGwtEvent { 
}

//than, event pretty simple
public class FooEvent extends UniGwtEvent  {
}
//replaced GwtEventHandler. You should not create special handler class per event!
public interface UniEventHandler<T extends UniGwtEvent> {
    void handle(T event);
}
//event bus prototype(in pseudocode)
class UniEventBus {
    //map. keys getted from class. as I understand, it's possible from GWT 1.5 see http://code.google.com/p/google-web-toolkit/issues/detail?id=370 
    public <T extends UniGwtEvent> void addListener(Class<T> event, UniEventHandler<T> handler){
        map.put(event.getName(), handler);
    }
    public void fireEvent(UniGwtEvent event){
        if(map.contains(event.getClass().getName())){
            map.get(event).handle(event);
        }
    }
}

用法

eventBus.addListener(FooEvent.class, new UniEventHandler<FooEvent>(){
    @Override
    public void handle(FooEvent event) {
        bla-bla
    }
});
eventBus.fireEvent(new FooEvent());

我认为这个解决方案要好得多,因为您不应该进行不必要的Type操作并为每个事件创建处理程序类。我只看到一个缺点——您应该在创建处理程序时指定泛型类型。但我认为还有许多其他的缺点或问题使得这个解决方案不可能实现。它们是什么


共 (2) 个答案

  1. # 1 楼答案

    使用您的实现没有明显的优势。正如我读到的,你的和GWT的EventBus之间有两个区别:

    1. 使用Strings而不是Type对象将事件处理程序绑定到事件类型。这并不是一个有意义的区别——在应用程序中使用更多类型不会带来任何损失,我怀疑在运行时,Strings使用的资源将略多于Types

    2. 直接将事件分派给相应的处理程序,而不是委派给事件类型。我更喜欢GWT的方法,因为它提供了事件调度方式的灵活性。例如,您可能希望处理程序实现两个不同的方法,根据事件的上下文调用这两个方法。以以下(琐碎的)例子为例:

      public class ExampleEvent extends GwtEvent<ExampleEvent.Handler> {
        public interface Handler extends EventHandler {
          void onExample(Integer id);
          void onExample(String name);
        }
      
        private final Integer id;
        private final String name;
      
        public ExampleEvent(Integer id) {
          this.id = id;
          this.name = null;
        }
      
        public ExampleEvent(String name) {
          this.name = name;
          this.id = null;
        }
      
        public void dispatch(Handler handler) {
          if (name != null) {
            handler.onExample(name);
          } else {
            handler.onExample(id);
          }
        }
      }
      

      在这种情况下,将分派委派给事件允许我们采取必须对每个处理程序执行的操作(确定事件是否包含id或名称),而无需在每个单独的事件处理程序中执行测试

    我建议使用GWT的EventBus实现——它可以工作,并且经过测试

  2. # 2 楼答案

    还有其他一些事件总线实现可以做得很好。我最近创建了一个非常高效的事件总线(Mbassador),我已经在生产中使用了一段时间了。它托管在github上,欢迎您查看

    https://github.com/bennidi/mbassador

    另一个选择是使用GoogleGuavas事件总线,但它缺少一些有用的功能(这就是为什么我实现了自己的解决方案)

    编辑:我为一系列可用的事件总线实现(包括Guava、MBassador等)创建了性能和功能比较。结果很有趣。看看这里 http://codeblock.engio.net/?p=37