我正在尝试创建一个系统来响应应用程序中发生的事件,类似于Observer模式。在我的系统中,EventProducer
的触发事件和EventConsumer
响应这些事件,并且两者通过中央集线器连接:
目前,我将忽略EventProducer
,而专注于EventHub
和EventConsumer
:
interface EventConsumer<E extends Event> {
void respondToEvent(E event);
}
class EventHub {
private HashMap<Class</*event type*/>, HashSet<EventConsumer</*event type*/>>> subscriptions;
public <E extends Event> void fireEvent(E event) {
/* For every consumer in the set corresponding to the event type {
consumer.respondToEvent(event);
} */
}
public <E extends Event> void subscribeToEvent(EventConsumer<E> consumer) {
/* Insert consumer into the set corresponding to E */
}
}
问题出在
HashMap
的声明中:我希望能够做类似的事情HashMap<Class<E extends Event>, HashSet<EventConsumer<E>>>
// or
<E extends Event> HashMap<Class<E>, HashSet<EventConsumer<E>>>
这样
EventConsumer
就可以通过Class
的相同类型进行参数化,但是我能得到的最接近的是HashMap<Class<? extends Event>, HashSet<EventConsumer<? extends Event>>>
但是,这将允许将
HashSet<EventConsumer<MouseClickEvent>>
和Class<KeyPressEvent>
子类KeyPressEvent
都分配给MouseClickEvent
之类的东西。第二个问题是
Event
:我需要能够将使用者存储在与其事件对应的正确集中,例如subscriptions.get(E.class).put(consumer)
但我在运行时无法获得E类。
我该如何解决这些问题?我会以错误的方式处理吗?
最佳答案
您可以从EventConsumer
类中删除泛型。但是您必须在EventConsumer
的每个实现中强制转换Event对象。
interface EventConsumer {
void respondToEvent(Event event);
}
class ClickEventConsumer implements EventConsumer {
public void respondToEvent(Event event){
ClickEvent ce = (ClickEvent)event;
//...
}
}
class EventHub {
private HashMap<Class<? extends Event>, HashSet<EventConsumer>> subscriptions;
public void fireEvent(Event event) {
HashSet<EventConsumer> consumers = subscriptions.get(event.getClass());
if (consumers != null){
for (EventConsumer ec : consumers){
ec.respondToEvent(event);
}
}
}
public void subscribeToEvent(Class<? extends Event> clazz, EventConsumer consumer) {
HashSet<EventConsumer> consumers = subscriptions.get(clazz);
if (consumers == null){
consumers = new HashSet<EventConsumer>();
subscriptions.put(clazz, consumers);
}
consumers.add(consumer);
}
}