我现在开始使用 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类。我只看到一个缺点 - 你应该在处理程序创建时指定泛型类型。但我认为还有许多其他缺点或问题使得这个解决方案变得不可能。它们是什么?
答案 0 :(得分:4)
使用您的实现没有明显的优势。当我读到它时,你和GWT EventBus
之间存在两个不同之处:
使用Strings
代替Type
个对象将事件处理程序绑定到事件类型。这不是一个有意义的区别 - 在您的应用程序中有更多类型没有任何惩罚,我怀疑,在运行时,Strings
将使用比Types
更多的资源。
直接将事件分派给适当的处理程序,而不是委托给事件类型。我更喜欢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>
我建议使用GWT的EventBus
实现 - 它可以正常运行并进行测试。
答案 1 :(得分:3)
还有其他事件总线实现可以做得很好。我最近创建了一个非常有效的事件总线(Mbassador),我已经在生产中使用了一段时间。它托管在github上,欢迎您来看看。
https://github.com/bennidi/mbassador
另一个选择是使用google guavas事件总线,但它缺少一些有用的功能(这就是我实现自己的解决方案的原因)
编辑:我为一系列可用的事件总线实现创建了性能和功能比较,包括Guava,MBassador等等。结果非常有趣。在这里查看 http://codeblock.engio.net/?p=37