9

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.

4

3 回答 3

1

使用instanceof是不受欢迎的,因为它经常出现在暗示不完整封装的上下文中。例如,instanceof有时用于区分不同种类的对象,然后根据它们的类型对它们进行操作。一种更简洁的方法是将代码放入对象的相应类中,并改为使用多态性。因此,与其从不使用instanceof,不如问问自己,您当前使用的instanceof是否合法

换句话说: 是否可以将依赖于实体类型的代码移动到对应的实体类中?当然,一旦得出结论,就应该记录下来,因为事情可能会发生变化。

顺便说一句,我认为您可以使用 a轻松概括您当前的设计Map<Class,List<Entity>>,这将允许您为任意数量的类型保留实体列表。Class[] types = {...}您还可以拥有一个包含所有需要区分的类型的数组。现在,您的方法中的循环中只需要一个instanceof运算符,它将遍历所有需要区分的类型,并将实体添加到所有相关列表中/从所有相关列表中删除。foradd/removeEntity(...)

于 2012-04-09T20:00:15.980 回答
1

您可以在这里使用访问者模式,本教程中的访问者模式使用它来解决您遇到的类似问题。 http://www.youtube.com/watch?v=KSEyIXnknoY

于 2012-04-09T05:08:42.143 回答
0

在我看来,您在世界级中为可碰撞对象使用额外的字段似乎是合理的,因为它是数据的特殊子集,需要专门处理。

不过,我唯一会改变的(主要是由于个人喜好)是使用List<Collidable>as 类型,因为根据您的需要 - 遍历所有这些以进行碰撞检查 - 列表是一种更快、更轻量级的方法。

于 2012-04-09T14:19:24.077 回答