2011-04-19 20 views
2

instanceofやそれに相当するもの(http://www.javapractices.com/topic/TopicAction.do?Id=31when should we use instanceof and when not)を使用するのは悪いデザインだと聞いていますが、これは主にコードを再利用するのが難しくなるためです。instanceofに代わるものはありますか?

しかし、場合によっては、私はinstanceofの良い代替手段を見つけるのが難しいと感じました。たとえば、リアルタイム戦略ゲームを作りたいとします。ゲームは、障害物、建物、タンクから構成され、すべてグリッドに配置され、各エンティティはグリッド内の1つのユニットを正確に占有します。そこで私はクラスObstacle、Building、Tankのスーパークラスである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を使用する他の方法はありますか?

ありがとうございます! Martin

答えて

1

グリッドは、エンティティのインスタンスで構成されます。各更新の間、私は各タンクが範囲内の敵のタンクを照準して撃つことを望む。したがって、これを行う簡単な方法は、各タンクがタンク範囲内のすべてのエンティティをグリッドに照会し、これらのすべてのエンティティを繰り返し処理して、それらがクラスタンクのインスタンスであるかどうかを確認することです。

リストを直接フィルタリングするだけではないのはなぜですか?

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

Tanksの代わりに、それらをターゲットにするエンティティのプロパティについて質問する必要があります。これは、基本クラスでfalseを返す可能性があります。また、後で呼び出すTankやその他のクラスによってオーバーライドされる可能性があります。

0

さて、あなたがタンクであるかどうかを確認するために、範囲内のすべてのエンティティではなく、範囲内にいるかどうかをすべてのタンクで繰り返し検討しましたか?繰り返しとインスタンスコールの両方で多くの時間を節約できるようです...

0

一般に、多形性は不必要なinstanceof演算子を回避する方法です。

0

Visitorを使用してこの動作を処理する必要があるかどうかわかりません。あなたのケースは、一般的な多型を使用することによって非常に簡単に達成できます。私は当初はファクトリメソッドと型変数を提案しようとしていましたが、その解決策はさらに単純になりました。

あなたは一般的な抽象スーパークラスを持っています。 (エンティティ)。このクラスでは、hitByMissile()(または何でも)というメソッドを定義できます。タンククラスでは、hitByMissileを作ることができます。あなたのコードは、各エンティティの振る舞いを決めるべきではありません。その振る舞いはオブジェクト自体によって定義されるべきです。したがって、エンティティを繰り返し処理してメソッドを呼び出すことができます。第二のためのあなたのビジターソリューション忘れ、そしてちょうどあなたの要件を上の集中

+0

私はこの問題を理解していないかもしれないという免責事項とともに、私のすべての回答を開始するこの習慣を持っています。これは一般的な卑劣さから脱出することですが、解決策がうまくいかない場合はコメントしてください。 –

関連する問題