Обзор автобуса событий

Я начинаю с GWT и сейчас изучаю концепции Event bus. Я нахожу это решение чрезвычайно сложным. Поэтому я попытался упростить его, написав прототип самостоятельно, чтобы увидеть все проблемы.

Сначала я напишу о своем понимании шины событий (что может быть совершенно неправильно). У нас есть такие мероприятия

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 манипуляции и создавать класс обработчика для каждого события. Я вижу только один недостаток - вы должны указать универсальный тип при создании обработчика. Но я полагаю, что есть много других недостатков или проблем, которые делают это решение невозможным. Кто они такие?


person Stan Kurilin    schedule 04.03.2011    source источник


Ответы (2)


Нет очевидного преимущества в использовании вашей реализации. Когда я прочитал это, между вашим и 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);
        }
      }
    }
    

    В этом случае делегирование отправки событию позволяет нам выполнить действие, которое должно быть выполнено для каждого обработчика (определение того, содержит ли событие идентификатор или имя), не требуя, чтобы проверка выполнялась в каждом отдельном обработчике событий.

Я рекомендую использовать реализацию GWT EventBus — она работает и проверена.

person Jason Terk    schedule 04.03.2011
comment
Спасибо @Jason. Конечно, я буду использовать реализацию GWT EventBus. Я задал этот вопрос только для уточнения наследия таких решений. 1) Я считаю свое решение предпочтительнее, так как разработчик не должен прилагать никаких усилий с Type манипуляциями, и я не вижу реальных недостатков. 2) Хороший вопрос с двумя методами, я не думал об этом раньше. Но стоит ли закладывать такую ​​логику в событие? Знаете ли вы какой-нибудь действительно хороший пример такого подхода? - person Stan Kurilin; 04.03.2011
comment
Я добавлю пример в свой ответ. - person Jason Terk; 04.03.2011

Существуют и другие реализации шины событий, которые хорошо справятся со своей задачей. Недавно я создал очень эффективную шину событий (Mbassador), которую уже некоторое время использую в производстве. Он размещен на github, и вам предлагается взглянуть.

https://github.com/bennidi/mbassador

Другим вариантом было бы использовать шину событий google guavas, но в ней отсутствуют некоторые полезные функции (поэтому я реализовал свое собственное решение)

РЕДАКТИРОВАТЬ: я провел сравнение производительности и функций для ряда доступных реализаций шины событий, включая Guava, MBassador и некоторые другие. Результаты довольно интересные. Посмотрите здесь http://codeblock.engio.net/?p=37.

person bennidi    schedule 23.10.2012
comment
Спасибо. Просто добавил еще несколько примеров кода в репозиторий, чтобы проиллюстрировать его использование. Думаю, в ближайшем будущем я опубликую сравнение скорости с другими реализациями шины. - person bennidi; 28.10.2012