Sto lavorando su un framework di processore di eventi per un semplice gioco che sto scrivendo, in cui più tipi di eventi sono gestiti in un loop. Dato che questi eventi portano distinti dati (ad esempio, uno trasporta un giocatore e una posizione, un altro porta un messaggio e un timestamp), ho finito per creare classi diverse per loro (anche se tutti implementano un'interfaccia comune, che è attualmente un'interfaccia marker).
All'interno del mio event processor, ho, per ogni tipo di evento, una serie di gestori di eventi che implementano un'interfaccia corrispondente (ad esempio una classe anonima che implementa PlayerInteractHandler
che gestisce PlayerInteractEvent
s). Poiché queste interfacce vengono implementate tramite un motore Javascript (Rhino) non riesco a utilizzare una singola interfaccia generica.
Nel tentativo di implementare il motore attuale, ho attualmente il codice come segue (metodi in linea per mostrare l'idea dietro il codice in una rappresentazione più compatta):
if (recvdEvent instanceof FooEvent){
// getHandlerList() returns a List<EventHandler> due to limitations of generics
for(EventHandler eh : getHandlerList(FooHandler.class) {
FooEvent eventAfterCast = (FooEvent) recvdEvent
}
}
Ovviamente ci sono altri blocchi else if (recvdEvent instanceof BarEvent)
, e prendo e gestisco ClassCastExceptions.
Il problema con questo, è che sembra un cattivo uso di un linguaggio orientato agli oggetti, e devo verificare rigorosamente l'altro codice a mano per mantenere la sicurezza del tipo.
Le altre alternative che conosco sono che il mio evento restituisca il Class<? extends EventHandler>
in un certo metodo, per usare il polimorfismo / dispacciamento dinamico, ma che richiederebbe un cast riflettente o un metodo polimorfico nella classe del gestore che romperebbe ancora il tipo di sicurezza (e un altro livello in cima all'interfaccia stessa).
I processori di eventi multipli porterebbero alla duplicazione del codice e implicherebbero thread separati per ciascuno come viene progettato l'attuale processore di eventi. Se dovessi conservare un singolo thread e un processore avrei bisogno di una singola coda, il cui tipo dichiarato è AbstractQueue<GameEvent>
, e sarei di nuovo al punto di partenza.
Mi sto avvicinando a questo in modo completamente errato?