活动巴士审查

时间:2011-03-04 11:55:16

标签: java gwt event-bus

我现在开始使用 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操作并为每个事件创建Handler类。我只看到一个缺点 - 你应该在处理程序创建时指定泛型类型。但我认为还有许多其他缺点或问题使得这个解决方案变得不可能。它们是什么?

2 个答案:

答案 0 :(得分:4)

使用您的实现没有明显的优势。当我读到它时,你和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或名称),而不要求在每个单独的事件处理程序中执行测试。 / p>

  3. 我建议使用GWT的EventBus实现 - 它可以正常运行并进行测试。

答案 1 :(得分:3)

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

https://github.com/bennidi/mbassador

另一个选择是使用google guavas事件总线,但它缺少一些有用的功能(这就是我实现自己的解决方案的原因)

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