I am writing a simulator that has several interfaces which all simulated objects implement. The Entity
interface has methods that all objects must have, such as ID retrieval and advancing the time step for the object's state. Collidable
extends Entity
, and represents anything with volume and position that should be considered when collision detection algorithms run. Field
extends Entity
, and represents anything that maps a location to a value; these are used to model things like magnetic fields that permeate the world but have no volume or physical form. RigidBody
is a class that implements Collidable
and provides rigid-body dynamics algorithms. I have a World
class which manages all Entities
and has methods for advancing the simulator's clock and partitioning the world so as to make collision detection more efficient.
My issue involves retrieving Entity
subtypes from World
. Originally, World
just had a map of Entities
keyed by ID, and to retieve a Field
or RigidBody
there would be methods that would grab the Entity
out of the map and do an instanceof
check plus a cast to the desired subtype. I'm well-aware that instanceof
usage is frowned upon, however, so I tried another approach.
Currently, I have separate maps within World
for each interface. For instance, there is a map for Collidables
as well as a map for all Entities
. The addCollidable()
method will add to both maps, and getCollidable()
will retrieve only from the Collidable
map. This avoids instanceof
, but it still seems like poor design to me. If I dream up another interface to extend Entity
, I'll need another map in World
and corresponding methods.
I feel like this issue isn't terribly obscure, so what is typically done in this situation?
EDIT
I don't believe the Visitor pattern will work here, as Visitor allows you to dispatch on the concrete type, and some of my retrieval methods need to retrieve interface types. For instance, Visitor would work if World
only needed methods to retrieve RigidBodies
and other such concrete classes, but I cannot make a method that retrieves all Collidables
with Visitor.
Here what you can use is visitor pattern, This tutorial on Visitor Pattern use it against a similar issue you are having. http://www.youtube.com/watch?v=KSEyIXnknoY
Using instanceof
is frowned upon because it often appears in contexts where it hints at incomplete encapsulation. For example, instanceof
is sometimes used to distinguish between different kinds of objects and then operates on them depending on their type. A cleaner way of doing this could be to put the code into the corresponding classes of the objects and to use polymorphism instead. So, instead of never using instanceof
, rather ask yourself whether your current use of instanceof
might be legitimate?
In other words: Is it possible to move the code that depends on the type of the entity into the corresponding entity class? (Of course, once you reach a conclusion this should be documented, as things may change.)
BTW I think you can easily generalize you current design by using a Map<Class,List<Entity>>
, which would allow you to keep entity lists for an arbitrary number of types. You could also have an array Class[] types = {...}
that contains all types that need to be distinguished.
Now you only need a single instanceof
operator in a for
loop within your add/removeEntity(...)
methods, which would walk through all the types that need to be distinguished and adds/removes the entity to/from all relevant lists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With