2012-04-09 15 views
9

Estoy escribiendo un simulador que tiene varias interfaces que implementan todos los objetos simulados. La interfaz Entity tiene métodos que todos los objetos deben tener, como la recuperación de ID y avanzar el paso de tiempo para el estado del objeto. Collidable se extiende a Entity, y representa cualquier cosa con volumen y posición que deba considerarse cuando se ejecutan los algoritmos de detección de colisión. Field se extiende Entity, y representa cualquier cosa que mapea una ubicación a un valor; estos se usan para modelar cosas como campos magnéticos que impregnan el mundo pero no tienen volumen ni forma física. RigidBody es una clase que implementa Collidable y proporciona algoritmos de dinámica de cuerpo rígido. Tengo una clase World que gestiona todos los Entities y tiene métodos para avanzar el reloj del simulador y dividir el mundo para hacer que la detección de colisiones sea más eficiente.¿Cuál es un buen patrón para almacenar implementaciones de una interfaz y recuperar implementaciones específicas?

Mi problema consiste en recuperar Entity subtipos desde World. Originalmente, World tenía un mapa de Entities tecleado por ID, y para recuperar Field o RigidBody, habría métodos que tomarían el Entity fuera del mapa y harían una verificación instanceof más un molde para el subtipo deseado. Soy consciente de que el uso de instanceof está mal visto, sin embargo, así que probé con otro enfoque.

Actualmente, tengo mapas separados dentro de World para cada interfaz. Por ejemplo, hay un mapa para Collidables, así como un mapa para todos Entities. El método addCollidable() se agregará a ambos mapas y getCollidable() solo se recuperará del mapa Collidable. Esto evita instanceof, pero todavía me parece un diseño pobre. Si imagino otra interfaz para ampliar Entity, necesitaré otro mapa en World y los métodos correspondientes.

Siento que este problema no es terriblemente oscuro, entonces ¿qué se suele hacer en esta situación?

EDITAR

No creo que el patrón de Visitantes trabajará aquí, como Visitador le permite despachar el tipo de hormigón, y algunos de mis métodos de recuperación necesario para recuperar los tipos de interfaz. Por ejemplo, Visitor funcionaría si World solo necesitara métodos para recuperar RigidBodies y otras clases de concreto, pero no puedo hacer un método que recupere todo Collidables con Visitor.

+2

Puede tener algo como ' T getEntityFromMap (Clase clazz)', este método elimina la necesidad del mapa 'Collidables', y solo pide' getEntityFromMap (Entity.class) 'para obtener un Entidad en su caso más general, y .... –

Respuesta

1

Aquí lo que puede usar es patrón de visitante, este tutorial sobre Patrón de visitante lo usa contra un problema similar que está teniendo. http://www.youtube.com/watch?v=KSEyIXnknoY

+0

Esto está cerca de lo que necesito, pero desafortunadamente los envíos de visitantes en tipos concretos, y requiero la capacidad de despachar en tipos abstractos/de interfaz, así como en tipos concretos. – derefed

0

Me parece plausible que utilice un campo adicional para los colisionables en su clase mundial, ya que es un subconjunto especial de datos, que requiere un manejo especializado.

La única cosa que cambiaría (sobre todo debido al gusto personal), sin embargo, es el uso de List<Collidable> como tipo, ya que para sus necesidades - iteración a través de todos ellos para los controles de colisión - Una lista es un & enfoque más ligero más rápido.

+0

La pregunta que tendría aquí es que cuando se agrega un objeto 'obj' que implementa' Collidable' a 'World', ¿cómo' World' podrá decir que 'obj' debe ponerse en' List ' sin usar un cheque 'instanciaof' – derefed

+0

Supongo que ya tiene algo como 'World.addEntity (Entity newEntity)' Simplemente agregue 'World.addEntity (Collidable newCollidable)', impleméntelo apropiadamente y deje que javac maneje el resto. – KJP

1

Usando instanceof es mal visto porque menudo aparece en contextos en los que alude a la encapsulación incompleta. Por ejemplo, instanceof se usa a veces para distinguir entre diferentes tipos de objetos y luego opera en ellos dependiendo de su tipo.Una forma más limpia de hacer esto podría ser poner el código en las clases correspondientes de los objetos y usar polymorphism en su lugar. Entonces, en lugar de nunca usando instanceof, en cambio pregúntese si su uso actual de instanceof podría ser legítimo?

En otras palabras: ¿Es posible mover el código que depende del tipo de entidad a la clase de entidad correspondiente? (Por supuesto, una vez que llegue a una conclusión esto debe ser documentado, ya que las cosas pueden cambiar.)

Por cierto creo que se puede fácilmente que generalizar diseño actual mediante el uso de un Map<Class,List<Entity>>, que le permitiría a mantener listas de entidades para un número arbitrario de tipos. También podría tener una matriz Class[] types = {...} que contiene todos los tipos que deben distinguirse. Ahora solo necesita un único operador instanceof en un bucle for dentro de sus métodos add/removeEntity(...), que recorrería todos los tipos que deben distinguirse y agregará/eliminará la entidad a/de todas las listas relevantes.

Cuestiones relacionadas