Come gestirò un insieme di classi di eventi differenti con interfacce di gestori differenti in un singolo processore di eventi?

0

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?

    
posta hexafraction 01.03.2014 - 21:52
fonte

1 risposta

1

Modello visitatore

Non sarà di aiuto qui. Lo scenario migliore per adottare Visitor Pattern è che hai un numero fisso di sottoclassi. Tuttavia, nel tuo esempio, potresti avere molto di Event in futuro. Pertanto, se scegli di utilizzare Visitor Pattern , ogni volta che aggiungi un nuovo tipo di Event , devi modificare Visitor . È un incubo.

riflessione

È la strada giusta da percorrere. Devi sacrificare la sicurezza del tipo per un dispatching più dinamico. Ma possiamo fare qualcosa per migliorare la sicurezza.

Guava EventBus usa reflection e annotation per fornire sia la sicurezza di compilazione che di runtime . Puoi verificare l'implementazione se sei interessato. In breve, sacrifica un po 'di sicurezza (potresti avere un evento che non ha un gestore corrispondente, che penso sia ragionevole, ma potrebbe non essere adatto al tuo caso), ma quello che ottieni è un codice più pulito e gestibile.

    
risposta data 06.06.2015 - 23:30
fonte

Leggi altre domande sui tag