我认为Event API一般应该包括以下内容:
-
类型安全,避免转换事件/事件类型类 - 它将使您免于将来出现意外的类转换异常。
-
对开发人员友好。 API 应该简短而甜美。您应该能够在 IDE(例如 Intellij IDEA 或 Eclipse)中轻松找到合适的侦听器。类型安全将为您提供。
- 添加新事件类型应该简单快捷。
- 事件结构应该是可重用的。
这是一种可能的方法:
创建基础事件和更复杂的事件结构。
class BaseEvent {
}
class ComplexEvent extends BaseEvent {
int importantData;
public ComplexEvent(int i) {
importantData = i;
}
}
为EventType创建一个单独的类,使每个事件类型依赖于事件。我们现在可以为我们的事件类型重用现有结构。在不破坏现有代码的情况下添加新事件也很容易。
final class EventType<E> {
private EventType(){}
public final static EventType<BaseEvent> SimpleEvent = new EventType<BaseEvent>();
public final static EventType<BaseEvent> SimpleEvent2 = new EventType<BaseEvent>();
public final static EventType<ComplexEvent> ComplexEvent1 = new EventType<ComplexEvent>();
public final static EventType<ComplexEvent> ComplexEvent2 = new EventType<ComplexEvent>();
}
将侦听器创建为通用接口,依赖于事件。
interface Listener<E extends BaseEvent> {
void handle(E event);
}
在EventSource中使用这些类,为指定的事件类型注册监听器。
class EventSource {
private final Map<EventType, List<Listener<? extends BaseEvent>>> listenersMap = new HashMap<EventType, List<Listener<? extends BaseEvent>>>();
public <E extends BaseEvent> void addListener(EventType<E> eventType, Listener<E> listener) {
listeners(eventType).add(listener);
}
public <E extends BaseEvent> void fire(EventType<E> eventType, E event) {
for (Listener listener : listeners(eventType)) {
listener.handle(event);
}
}
private List<Listener<? extends BaseEvent>> listeners(EventType eventType) {
if (listenersMap.containsKey(eventType)) {
return listenersMap.get(eventType);
} else {
List<Listener<? extends BaseEvent>> listenersList = new ArrayList();
listenersMap.put(eventType, listenersList);
return listenersList;
}
}
}
检查 API 的使用,它允许我们在 Listener 的实现中获得正确的事件结构。
public static void main(String[] args) {
EventSource eventSource = new EventSource();
eventSource.addListener(EventType.SimpleEvent, new Listener<BaseEvent>() {
@Override
public void handle(BaseEvent event) {
log.info("Simple 1 handled!");
}
});
eventSource.addListener(EventType.SimpleEvent2, new Listener<BaseEvent>() {
@Override
public void handle(BaseEvent event) {
log.info("Simple 2 handled!");
}
});
// compile error! we must handle ComplexEvent type
// eventSource.addListener(EventType.ComplexEvent1, new Listener<BaseEvent>() {
// @Override
// public void handle(BaseEvent event) {
// log.info("Complex 1 handled!");
// }
// });
eventSource.addListener(EventType.ComplexEvent1, new Listener<ComplexEvent>() {
@Override
public void handle(ComplexEvent event) {
log.info("Complex 1 handled!" + event.importantData);
}
});
eventSource.addListener(EventType.ComplexEvent2, new Listener<ComplexEvent>() {
@Override
public void handle(ComplexEvent event) {
log.info("Complex 2 handled!" + event.importantData);
}
});
eventSource.fire(EventType.SimpleEvent, new BaseEvent());
eventSource.fire(EventType.SimpleEvent2, new BaseEvent());
eventSource.fire(EventType.ComplexEvent1, new ComplexEvent(1));
eventSource.fire(EventType.ComplexEvent2, new ComplexEvent(2));
// compile error! we must fire ComplexEvent to our listeners
//eventSource.fire(EventType.ComplexEvent1, new BaseEvent());
}
当您不需要传递任何特定数据时,您还可以将简写 fire 调用添加到 EventSource
public <E extends BaseEvent> void fire(EventType<E> eventType) {
fire(eventType, (E) new BaseEvent());
}
并从客户端代码中简单地使用它:
eventSource.fire(EventType.SimpleEvent);