开发者

Event bus review

开发者 https://www.devze.com 2023-02-14 15:47 出处:网络
I\'m starting with GWT and learning Event bus concepts now. I find this solution extremely complicated. So I tried to simplify it by writing prototype by myself to see all problems.

I'm starting with GWT and learning Event bus concepts now. I find this solution extremely complicated. So I tried to simplify it by writing prototype by myself to see all problems.

At first I will write about my understanding of event bus (that can be completely wrong). We have events like this

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);
    }
}

handler interface,

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

usage

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

Thats it. And now my prototype.

//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 Un开发者_StackOverflow中文版iEventBus {
    //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);
        }
    }
}

usage

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

I think this solution is much better since you shouldn't make unnecessary Type manipulation and create Handler Class per event. I see only one disadvantage - you should specify generic type on handler creation. But I suppose there are many other disadvantages or ever issues that makes this solution impossible. What are they?


There is no obvious advantage to using your implementation. As I read it there are two differences between yours and GWT's EventBus:

  1. Using Strings instead of Type objects to bind event handlers to event types. This is not a meaningful difference - there's no penalty to having more types in your application and I suspect that, at runtime, Strings will use slightly more resources than Types.

  2. Dispatching events to the appropriate handlers directly instead of delegating to the event type. I prefer GWT's approach here because it affords flexibility in how events are dispatched. One might, for example, want handlers to implement two different methods that are invoked depending on the context of the event. Take the following (trivial) example:

    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);
        }
      }
    }
    

    In this case delegating dispatch to the event allows us to take an action that must be performed for every handler (determining whether the event contains an id or a name) without requiring that the test be performed in every individual event handler.

I recommend using GWT's EventBus implementation - it works and it is tested.


There are other event bus implementations out there that will do a good job. I recently created a very efficient event bus (Mbassador) that I have been using in production for a while now. It's hosted on github and you are invited to take a look.

https://github.com/bennidi/mbassador

Another option would be to use google guavas event bus but it lacks some useful features (which is why I implemented my own solution)

EDIT: I created a performance and feature comparison for a selection of available event bus implementations including Guava, MBassador and some more. The results are quite interesting. Check it out here http://codeblock.engio.net/?p=37

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号