Próbuję stworzyć system reagowania na zdarzenia, które występują w mojej aplikacji, podobnie do wzorca obserwatora. W moim systemie, EventProducer
s wydarzenia spust i EventConsumer
s odpowiedzi na te wydarzenia, a dwa są połączone za pomocą centralnej piasty:Potrzebujesz pomocy przy użyciu Java Generics
Na razie mam zamiar ignorować EventProducer
i skupić się na EventHub
i 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 */
}
}
problem leży w deklaracji HashMap
: Chcę aby móc zrobić coś takiego
HashMap<Class<E extends Event>, HashSet<EventConsumer<E>>>
// or
<E extends Event> HashMap<Class<E>, HashSet<EventConsumer<E>>>
Tak, że EventConsumer
jest parametryzowane przez tego samego typu, Class
jest, ale najbliżej można uzyskać jest
HashMap<Class<? extends Event>, HashSet<EventConsumer<? extends Event>>>
Ale wtedy to pozwoliłoby rzeczy takie jak HashSet<EventConsumer<MouseClickEvent>>
jest przypisany do Class<KeyPressEvent>
, zakładając zarówno KeyPressEvent
i MouseClickEvent
podklasę Event
.
Drugim problemem jest subscribeToEvent
: Muszę być w stanie przechowywać konsumentów w prawidłowym zestawem odpowiadającym jego przypadku, podobnie jak w
subscriptions.get(E.class).put(consumer)
ale nie mogę dostać klasę E w czasie wykonywania .
Jak mogę rozwiązać te problemy? Czy podchodzę do tego w niewłaściwy sposób?
Właściwie to lubię to podejście. Pierwotnie chciałem móc zrobić coś w stylu 'class SomeConsumer implementuje EventConsumer, EventConsumer ', ale najwyraźniej nie możesz tego zrobić (co, jak sądzę, ma sens).Czy istnieje jakiś sposób, aby uzyskać pewien rodzaj polimorfizmu "zdarzenia" na konsumenta, aby uniknąć zmiany w 'responseToEvent'? Podobnie jak "void responseToEvent (ClickEvent); void replyToEvent (KeyPressEvent); '? –
@AustinHyde Nie wiem. Bawiłem się z tym, ale nie mogłem znaleźć dobrego sposobu, aby to zrobić bez tworzenia całego zamieszania generycznego w 'EventHub'. Powinieneś także wziąć pod uwagę czytelność kodu. Nawet jeśli działa to trochę nieefektywnie, jeśli z czasem łatwiej je utrzymać, myślę, że warto (chyba że piszesz grę komputerową lub wyszukiwarkę lub coś, co liczy milisekundy). Dla mnie wszystkie te generyczne kody utrudniają odczytanie i zrozumienie kodu. – Michael