2

instanceof または同等のものを使用するのは悪い設計だと聞いたことがあります ( http://www.javapractices.com/topic/TopicAction.do?Id=31、 instanceof を使用する必要がある場合と使用しない場合は? ) これには同意できますこれは主に、コードの再利用が難しくなる可能性があるためです。

ただし、場合によっては、instanceof に代わる優れた方法を思いつくのが難しいことがわかりました。たとえば、リアルタイム ストラテジー ゲームを作りたいとします。ゲームは障害物、建物、戦車で構成され、すべてグリッド上に配置され、各エンティティはグリッド内の 1 つのユニットを占有します。そこで、クラス Obstacle、Building、および Tank のスーパークラスであるクラス Entity を作成します。グリッドはエンティティのインスタンスで構成されます。各更新中に、各戦車が範囲内の敵戦車を狙って発砲するようにします。したがって、これを行う簡単な方法は、各タンクがグリッドにタンク範囲内のすべてのエンティティを要求し、これらすべてのエンティティを繰り返し処理して、クラス Tank のインスタンスであるかどうかを確認することです。

instanceof を使用する代わりに私の唯一の試みは、デザイン パターンVisitorを使用することでした。(entity->acceptVisitor(visitor))訪問者は、メソッドの 1 つまたは を呼び出すvisitor->visitObstacle(this)エンティティvisitor->visitBuildig(this)によって受け入れられvisitor->visitTank(this)ます。ただし、これにより、多数のビジターを作成する必要があり、エンティティに対して作成したいタスクごとにほぼ 1 つの新しいビジターを作成する必要がありました。もう 1 つの問題は、エンティティがどのクラスから構築されているかに関係なく、多くの場合、ビジターがエンティティに対して同じメソッドを呼び出すことです。これは、たとえば、エンティティが別のエンティティが静止しているかどうかを確認したい場合に発生する可能性があります。

#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 を使用する他の方法はありますか?

4

4 に答える 4

1

ビジターソリューションを一瞬忘れて、要件だけに集中します。

グリッドはエンティティのインスタンスで構成されます。更新のたびに、各戦車が範囲内の敵の戦車を狙って撃ちます。したがって、これを行う簡単な方法は、各タンクがタンク範囲内のすべてのエンティティをグリッドに要求し、これらすべてのエンティティを反復処理して、それらがクラスタンクのインスタンスであるかどうかを確認することです。

リストを直接フィルタリングしてみませんか?

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

戦車だけでなく、それらをターゲットにするエンティティのプロパティについて質問する必要があります。これにより、基本クラスでfalseが返され、後で起動する必要があるタンクやその他のクラスによってオーバーライドされる可能性があります。

于 2011-04-19T19:44:08.003 に答える
0

一般に、ポリモーフィズムは、不必要なinstanceof演算子を回避する方法です。

于 2011-04-19T19:39:39.767 に答える
0

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

つまり、一般的な抽象スーパークラスがあります。(実在物)。したがって、このクラスでは、hitByMissile()(またはその他)と呼ばれるメソッドを定義できます。戦車クラスでは、hitByMissileを作成して、障害物と言う場合とは異なるパフォーマンスを実行できます。コードは、各エンティティの動作を決定するべきではありません。動作は、オブジェクト自体によって定義する必要があります。したがって、エンティティを繰り返し処理してメソッドを呼び出すことができます。

于 2011-04-19T19:42:05.567 に答える
0

範囲内のすべてのエンティティが戦車かどうかを確認するのではなく、すべての戦車が範囲内にあるかどうかを確認することを検討しましたか? 反復と instanceof 呼び出しの両方で多くの時間を節約できるようです...

于 2011-04-19T19:37:07.053 に答える