Java 事件总线回顾
我现在从GWT开始学习事件总线概念。我觉得这个解决方案非常复杂。所以我试图通过自己编写原型来简化它,以了解所有问题 首先,我将写下我对事件总线的理解(这可能是完全错误的)。 我们有这样的活动Java 事件总线回顾,java,gwt,event-bus,Java,Gwt,Event Bus,我现在从GWT开始学习事件总线概念。我觉得这个解决方案非常复杂。所以我试图通过自己编写原型来简化它,以了解所有问题 首先,我将写下我对事件总线的理解(这可能是完全错误的)。 我们有这样的活动 public class FooEvent extends GwtEvent<FooHandler> { public static Type<FooHandler> TYPE = new Type<FooHandler>(); //as event type i
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);
}
}
用法
eventBus.addHandler(FooEvent.TYPE, new FooHandler() {
@Override
public void someMethod(FooEvent event) {
//bla-bla
}
});
eventBus.fireEvent(new FooEvent());
eventBus.addListener(FooEvent.class, new UniEventHandler<FooEvent>(){
@Override
public void handle(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);
}
}
}
//替换了GwtEvent
接口UniGwtEvent{
}
//比这更简单
公共类FooEvent扩展UniGwtEvent{
}
//取代了格温坦德勒。您不应该为每个事件创建特殊的处理程序类!
公共接口UniEventHandler{
无效句柄(T事件);
}
//事件总线原型(伪代码)
类UniEventBus{
//map.keys是从类中获取的。据我所知,它可能来自GWT1.5,请参见http://code.google.com/p/google-web-toolkit/issues/detail?id=370
public void addListener(类事件,UniEventHandler){
put(event.getName(),handler);
}
公共无效火灾事件(UniGwtEvent事件){
if(map.contains(event.getClass().getName())){
map.get(事件)、handle(事件);
}
}
}
用法
eventBus.addHandler(FooEvent.TYPE, new FooHandler() {
@Override
public void someMethod(FooEvent event) {
//bla-bla
}
});
eventBus.fireEvent(new FooEvent());
eventBus.addListener(FooEvent.class, new UniEventHandler<FooEvent>(){
@Override
public void handle(FooEvent event) {
bla-bla
}
});
eventBus.fireEvent(new FooEvent());
eventBus.addListener(FooEvent.class,新的UniEventHandler(){
@凌驾
公共无效句柄(FooEvent事件){
布拉布拉
}
});
fireEvent(新的FooEvent());
我认为这个解决方案要好得多,因为您不应该对每个事件进行不必要的
类型操作和创建处理程序类。我只看到一个缺点——您应该在创建处理程序时指定泛型类型。但我认为还有许多其他的缺点或问题使得这个解决方案不可能实现。它们是什么?使用您的实现没有明显的优势。正如我所读到的,您的和GWT的EventBus
之间有两个区别:
使用字符串
而不是类型
对象将事件处理程序绑定到事件类型。这并不是一个有意义的区别-在应用程序中使用更多类型不会带来任何损失,我怀疑在运行时,字符串
将比类型
使用略多的资源
直接将事件分派给相应的处理程序,而不是委派给事件类型。我更喜欢GWT的方法,因为它提供了事件调度方式的灵活性。例如,您可能希望处理程序实现两个不同的方法,根据事件的上下文调用这两个方法。以以下(琐碎的)例子为例:
公共类ExampleEvent扩展了GwtEvent{
公共接口处理程序扩展了EventHandler{
void-onExample(整数id);
void onExample(字符串名称);
}
私有最终整数id;
私有最终字符串名;
公共示例事件(整数id){
this.id=id;
this.name=null;
}
公共示例事件(字符串名称){
this.name=名称;
this.id=null;
}
公共无效调度(处理程序){
if(name!=null){
handler.onExample(名称);
}否则{
handler.onExample(id);
}
}
}
在这种情况下,将分派委派给事件允许我们采取必须对每个处理程序执行的操作(确定事件是否包含id或名称),而无需在每个单独的事件处理程序中执行测试
我建议使用GWT的EventBus
实现—它可以工作,并且经过测试。还有其他的事件总线实现可以做得很好。我最近创建了一个非常高效的事件总线(Mbassador),我已经在生产中使用了一段时间了。它托管在github上,欢迎您查看
另一个选择是使用GoogleGuavas事件总线,但它缺少一些有用的功能(这就是为什么我实现了自己的解决方案)
编辑:我为一系列可用的事件总线实现(包括Guava、MBassador等)创建了性能和功能比较。结果很有趣。看看这里
谢谢@Jason。当然,我将使用GWT的EventBus
实现。我问这个问题只是为了澄清这些解决方案的“遗产”。1) 作为开发人员,我认为“我的”解决方案更可取,不应该在类型操作方面做出任何努力,我看不到真正的缺点。2) 有两种方法很好,我以前没有考虑过这一点。但你们应该把这种逻辑放在事件中吗?你知道这种方法有什么真正好的例子吗?我会在我的答案中加上一个例子。谢谢。只是在repo中添加了一些示例代码,以进一步说明其用法。我想,在不久的将来,我将发布一个与其他总线实现的速度比较。