[英]Events with different types and data
我正在用Java写一个库,该库根据类型抛出具有不同数据的不同类型的事件。
例如,这是扩展的EventObject:
public class FooEvent extends EventObject {
private final int eventType;
private final Object fooEventObject;
public FooEvent(int type, Object obj){/*...*/}
public int getEventType() {/*...*/}
public int getEventObject() {/*...*/}
}
这是我的听众当前的样子:
FooEventListener listener = new FooEventListener() {
@Override
public void onDataChange(FooEvent event) {
switch(event.getEventType()) {
case EVENT_TYPE_BAR:
Bars bar = (Bars)event.getEventObject();
/*work with Bar object...*/
break;
case EVENT_TYPE_GOO:
Goo goo = (Goo)event.getEventObject();
/*work with Goo object...*/
break;
/* etc ...*/
}
}
}
我想知道这是否是解决此问题的正确方法(尽管我怀疑是这样,因为库的用户需要知道要转换为哪种类型),其中我的对象具有不同的事件类型,而我没有想要为每个事件创建一个不同的事件和侦听器。
番石榴的EventBus提供了一种略有不同的方法,可以处理多种事件类型。
不幸的是,没有一个简单的解决方案来拥有具有不同类型的类型安全事件系统。 对于每种类型,您要么必须具有1个侦听器/发布实现,要么需要向一侧介绍所有存在的事件类型。
有一种方法可以消除对instanceof
或switch (type)
和转换的需要: Visitor Pattern
该模式使用以下事实:事件对象知道它们自己的类型,这意味着它们可以调用正确的方法。 缺点是您需要一个包含所有类型的侦听器接口。
public class Test {
abstract static class EventObject {
protected abstract void deliver(EventListener listener);
}
static class AEvent extends EventObject {
@Override
protected void deliver(EventListener listener) {
listener.onAEvent(this);
}
}
static class BEvent extends EventObject {
@Override
protected void deliver(EventListener listener) {
listener.onBEvent(this);
}
}
interface EventListener {
void onAEvent(AEvent event);
void onBEvent(BEvent event);
// ...
}
private static final EventListener LISTENER = new EventListener() {
@Override
public void onBEvent(BEvent event) {
System.out.println("Got B Event! " + event);
}
@Override
public void onAEvent(AEvent event) {
System.out.println("Got A Event! " + event);
}
};
private static void notifyListeners(EventObject event) {
event.deliver(LISTENER);
}
public static void main(String[] args) {
notifyListeners(new AEvent());
notifyListeners(new BEvent());
}
}
解决此问题的更好方法是使用泛型。
public class FooEvent<T> extends EventObject {
private final T fooEventObject;
public FooEvent(T obj){/*...*/}
public T getEventObject() {/*...*/}
}
//usage
SomeType object = new SomeType();
new FooEvent<SomeType>(object);
我认为这是一种方法,但不是最干净的方法。 您应该创建一个抽象类
public abstract class AbstractEventType<T> extends EventObject {}
并从中扩展:
public abstract class FooEvent extends AbstractEventType<Foo> {}
public abstract class BarEvent extends AbstractEventType<Bar> {}
然后,您需要触发不同的事件,并且根据类型还需要具有不同的事件侦听器:
public interface FooEventListener {
public void onFooChange(FooEvent fooEvent);
}
等等
如果您只想使用一种事件类型,则可以通过为每种类型创建一个处理程序方法,例如至少将代码移动到框架中以确定该类型,并避免污染“业务”代码。
public interface MyEventListener {
public void onFooChange(EventType<Foo> eventType);
public void onBarChange(EventType<Bar> eventType);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.