我正在为我的课程编写事件源模板:
public class EventSource<E> {
protected ArrayList<E> listeners = new ArrayList<E>();
public void addListener(E listener)
{
listeners.add(listener);
}
public void removeListener(E listener)
{
listeners.remove(listener);
}
}
要发起一个事件我需要调用类似的东西:
for(SomeListener listener: listeners)
listener.onSomeEvent();
发起一个事件看起来很难看。有没有办法把更短的东西称为:
fire(SomeListener.onSomeEvent)
或
fire(onSomeEvent)
我已经找到了3个解决方案:
我使用java反射并将方法名称作为参数传递给模板中的某个方法,这将为所有侦听器调用此方法。但我认为由于需要解析字符串(方法名称)而效率低下。如何以不丑的方式传递参数 - 问题仍然存在。
II对所有方法使用相同的名称,但传递不同的参数:
public struct SomeEvent1
{
int someData;
}
public struct SomeEvent2
{
int someAnotherData;
double probablyMoreData;
}
public interface SomeListener
{
public void fire(SomeEvent1 e);
public void fire(SomeEvent2 e);
}
但即使我不需要任何参数,它也需要构建此事件结构。
III使用授权。想象一下,SomeEventSource扩展了EventSource。现在我可以调用onSomeEventI(),因为我在SomeEventSource中编写了这些方法:
public void onSomeEventI()
{
for(SomeListener listener: listeners)
listener.onSomeEventI();
}
但我无法在通用EventSource中编写这些方法,因为它与Listener无关。在SomeEventSource中编写这些方法会使通用的EventSource更有用,而不是有用的。
问题仍然存在:如何在短时间内发射事件?
答案 0 :(得分:2)
我认为事件API 通常应涵盖以下内容:
以下是可能的方法之一:
创建基本事件和更复杂的事件结构。
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);