2012-04-09 14 views
9

Sto scrivendo un simulatore che ha diverse interfacce che tutti gli oggetti simulati implementano. L'interfaccia Entity ha metodi che devono avere tutti gli oggetti, come il recupero dell'ID e l'avanzamento del passo temporale per lo stato dell'oggetto. Collidable estende Entity e rappresenta qualsiasi cosa con volume e posizione da tenere in considerazione quando vengono eseguiti algoritmi di rilevamento delle collisioni. Field estende Entity e rappresenta tutto ciò che associa una posizione a un valore; questi sono usati per modellare cose come i campi magnetici che permeano il mondo ma non hanno volume o forma fisica. RigidBody è una classe che implementa Collidable e fornisce algoritmi di dinamica del corpo rigido. Ho una classe World che gestisce tutto il Entities e ha metodi per far progredire l'orologio del simulatore e partizionare il mondo in modo da rendere più efficiente il rilevamento delle collisioni.Qual è un buon modello per la memorizzazione delle implementazioni di un'interfaccia e il recupero di implementazioni specifiche?

Il mio problema riguarda il recupero dei sottotipi Entity da World. Originariamente,aveva solo una mappa di Entities digitata per ID, e per recuperare un Field o RigidBody ci sarebbero metodi che afferrerebbero Entity dalla mappa e fare un controllo instanceof più un cast per il sottotipo desiderato. Sono ben consapevole del fatto che l'uso di instanceof sia disapprovato, tuttavia, ho provato un altro approccio.

Attualmente, ho mappe separate all'interno di World per ogni interfaccia. Ad esempio, c'è una mappa per Collidables e una mappa per tutti Entities. Il metodo addCollidable() verrà aggiunto a entrambe le mappe e lo standard getCollidable() verrà recuperato solo dalla mappa Collidable. Questo evita instanceof, ma mi sembra ancora un cattivo design. Se sago un'altra interfaccia per estendere Entity, ho bisogno di un'altra mappa in World e metodi corrispondenti.

Mi sembra che questo problema non sia terribilmente oscuro, quindi cosa viene fatto in genere in questa situazione?

EDIT

Io non credo che il modello Visitor funzionerà qui, come Visitatore consente di messaggio concernente il tipo concreto, e alcuni dei miei metodi di recupero ha bisogno di recuperare tipi di interfaccia. Ad esempio, Visitor funzionerebbe se i metodi World richiedessero solo i metodi per recuperare RigidBodies e altre classi concrete, ma non è possibile creare un metodo che recuperi tutti i dati Collidables con Visitor.

+2

Si può avere qualcosa come " T getEntityFromMap (Clase clazz)", questo metodo rimuove la necessità della mappa 'Collidables', e basta chiedere' getEntityFromMap (Entity.class) 'per ottenere un Entità nel suo caso più generale, e .... –

risposta

1

Qui è possibile utilizzare il modello di visitatore. Questo tutorial su Visitor Pattern lo utilizza in un problema simile a quello che si sta verificando. http://www.youtube.com/watch?v=KSEyIXnknoY

+0

Questo è vicino a ciò di cui ho bisogno, ma sfortunatamente i dispacci dei visitatori su tipi concreti, e richiedo la possibilità di inviare messaggi su tipi di interfaccia/astratti e tipi concreti. – derefed

0

Mi sembra plausibile che si utilizzi un campo aggiuntivo per i collidables nella classe mondiale, in quanto è un sottoinsieme speciale di dati che richiede una gestione specializzata.

L'unica cosa che avrei cambiato (per lo più a causa di gusto personale), però, sta usando List<Collidable> come tipo, perché per le vostre esigenze - iterazione attraverso tutti loro per i controlli di collisione - l'elenco è un & approccio più veloce e leggero.

+0

La domanda che vorrei qui è che quando un oggetto 'obj' che implementa' Collidable' viene aggiunto a 'World', come' World' sarà in grado di dire che 'obj' dovrebbe essere messo nella' Lista 'senza usare? un controllo 'instanceof'? – derefed

+0

Presumo che tu abbia già qualcosa come World.addEntity (Entity newEntity) ' Basta aggiungere' World.addEntity (Collidable newCollidable) ', implementalo in modo appropriato e lascia che javac gestisca il resto. – KJP

1

L'utilizzo di instanceof è corrugato perché è spesso appare in contesti in cui suggerisce un incapsulamento incompleto. Ad esempio, a volte viene utilizzato instanceof per distinguere tra diversi tipi di oggetti e quindi operare su di essi a seconda del loro tipo.Un modo più semplice per farlo potrebbe essere quello di inserire il codice nelle classi corrispondenti degli oggetti e utilizzare invece polymorphism. Quindi, invece di mai utilizzando instanceof, chiediti piuttosto se il tuo attuale utilizzo di instanceof potrebbe essere legittimo?

In altre parole: È possibile spostare il codice che dipende dal tipo di entità nella classe di entità corrispondente? (Naturalmente, una volta raggiunto una conclusione questo dovrebbe essere documentato, come le cose possono cambiare.)

BTW Penso che si può facilmente generalizzare design attuale utilizzando un Map<Class,List<Entity>>, che permetterebbe di mantenere gli elenchi di entità per un numero arbitrario di tipi. Si potrebbe anche avere un array Class[] types = {...} che contiene tutti i tipi che devono essere distinti. Ora è necessario un solo operatore instanceof in un ciclo all'interno dei propri metodi add/removeEntity(...), che dovrebbe esaminare tutti i tipi che devono essere distinti e aggiunge/rimuove l'entità da/a tutti gli elenchi pertinenti.

Problemi correlati