2011-04-19 68 views
2

我听说使用instanceof或同等设备(http://www.javapractices.com/topic/TopicAction.do?Id=31,when should we use instanceof and when not)是不好的设计,我可以达成一致,主要是因为它可以使代码难以重用。替代instanceof?

但是,在某些情况下,我发现很难想出一个好的替代instanceof。例如,假设我想制作一个实时策略游戏。游戏由障碍物,建筑物和坦克组成,全部放置在网格上,每个实体在网格中恰好占据一个单位。所以我创建了类Obstacle,Building和Tank的超类Class Entity。网格由实体的实例组成。在每次更新期间,我希望每个坦克瞄准并射击范围内的敌方坦克。所以,一个简单的方法就是每个坦克向坦克范围内的所有实体询问网格,然后遍历所有这些实体并检查它们是否是坦克类的实例。

我唯一的尝试作为使用instanceof的替代方案是使用设计模式Visitor。访问者被实体(entity->acceptVisitor(visitor))接受,该实体又调用方法visitor->visitObstacle(this),visitor->visitBuildig(this)visitor->visitTank(this)中的一种。然而,这迫使我创造了很多游客,对于我想要在实体上做的每一项任务,几乎都有一个新的参与者。另一个问题是,在许多情况下,访问者在实体上调用相同的方法,无论它构造了哪个类。

Python代码:

class StationaryEntityGatherVisitor: 
    def __init__(self): 
     self.stationaryEntities = [] 

    def visitObstacle(self, obstacle): 
     self._addIfStationary(obstacle) 

    def visitBuildig(self, building): 
     self._addIfStationary(building) 

    def visitTank(self, tank): 
     self._addIfStationary(tank) 

    def _addIfStationary(self, entity): 
     if entity.isStationary(): 
      self.stationaryEntities.append(entity) 

    def getStationaryEntities(): 
     return self.stationaryEntities 

我当然可以,让在此情况下,实体只是问,如果其他实体例如,这可以当实体要检查,如果另一个实体是固定的或不会发生它是直接静止的,而不是让游客那样做。但在这种情况下,我不会一致地检查实体的属性。要让实体询问某些财产(直接或通过访问者)的方法会有所不同,这取决于我是否需要检查实体类型,在我看来,似乎是一种非常奇怪的设计。

那么,你有没有其他的选择在上述问题中使用instanceof?

谢谢! 马丁

回答

1

忘记了一秒钟你的访问者的解决方案,并集中于只是你的要求:

的网格由实体的实例。在每次更新期间,我希望每个坦克瞄准并射击范围内的敌方坦克。所以,一个简单的方法就是每个坦克向坦克范围内的所有实体询问网格,然后遍历所有这些实体并检查它们是否是坦克类的实例。

为什么不直接过滤列表?

targetablesInRange = filter(isTargetable, grid.itemsInRangeOf(self)) 

而不仅仅是坦克,你应该问一个实体的属性,使他们成为一个目标。这可能会在基类中返回false,并被Tank和其他稍后介绍的应该被解雇的类重写。

0

那么,你有没有考虑迭代所有的坦克,看看他们是否在范围内,而不是范围内的所有实体,看看他们是坦克?似乎它会为迭代和instanceof调用节省大量时间...

0

通常,多态是避免不必要的instanceof操作符的方法。

0

我不知道你是否需要使用Visitor来处理这种行为。您的案例可以通过使用一般多态性很容易地完成。我最初是想建议一个工厂方法和类型变量,但解决方案可能更简单。

所以你有一个通用的抽象超类。 (实体)。所以在这个类中你可以定义一个名为hitByMissile()的方法(或其他)。在你的坦克课程中,你可以制作hitByMissile,表现不同,让我们说一个障碍。你的代码不应该决定每个实体的行为。行为应该由对象本身定义。所以你可以迭代实体并调用方法。

+0

我有这样的习惯,开始我所有的答案,并附有免责声明,我可能不知道这个问题:)。这是为了逃避一般的势利,但如果解决方案不适合你,请评论我。 – 2011-04-19 19:42:41