2

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

4

2 回答 2

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 或名称),而无需在每个单独的事件处理程序中执行测试。

我推荐使用 GWT 的EventBus实现——它可以工作并且已经过测试。

于 2011-03-04T18:34:51.950 回答
3

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

https://github.com/bennidi/mbassador

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

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

于 2012-10-23T08:43:31.967 回答