1

私はゲームをデザインしていて、自分がしていることの概要をよく理解しています。

ただし、OOPスキルを向上させようとしていますが、同じ問題に直面することがあります。抽象化されたオブジェクトをどのように使用すればよいですか?

画面上にxプロパティとyプロパティがあり、おそらく幅と高さがまだすべてを把握していないものを表すエンティティのリストがあるとします。

それから私は特別なタイプのエンティティを持っています。1つは移動でき、もう1つは移動できず、おそらく将来的には衝突可能のようなものです。

それらはすべてエンティティのコレクションにあり(List<Entity>私の場合)、移動してメインループ上のDynamicEntityのインスタンスであるエンティティをシミュレートしたいのですが、それらはすべてエンティティの抽象的なリストにあり、エンティティかどうかはわかりません動的エンティティであるかどうかにかかわらず、ループ内。

私はそれをチェックすることができることを知っていinstanceofますが、それは最善のアイデアではないと確信しています。

タイプをチェックするためにエンティティ内にブール値のようなものを持っている人を見たことがありますが、実際にはすべての種類のエンティティをハードコーディングしたくありません。

そのような場合のベストプラクティスを知りたいだけですか?

4

3 に答える 3

5

通常、可能であれば型のチェックは避けたほうがよいでしょう。コードで使用する必要があると思わinstanceofれる場合は、設計をより拡張可能にするために使用できる抽象化がおそらくあります。(将来、3 番目のタイプを追加することにした場合、戻ってすべてのチェックを 3 番目のケースでEntity更新する必要はありません。)instanceof

具体的な型をチェックせずに、インスタンスの具体的な型に基づいて異なるアクションを実行するには、2 つの一般的な方法があります。

一般的な方法の 1 つは、ビジター パターンです。ここでの考え方は、オブジェクトの種類ごとにアクションを持つ Visitor クラスを作成することです。次に、各具象クラスには、ビジター クラス内のaccept正しいメソッドを単純に呼び出すメソッドがあります。visitこの単一レベルの間接化により、タイプをチェックして選択するのではなく、オブジェクトが正しいアクションを選択することができます。

通常、訪問者パターンは次の 2 つの理由のいずれかで使用されます。1) クラスのソース コードにアクセスせずに、ビジター パターンを実装するクラス階層に新しいアクションを追加できます。新しいビジター クラスを実装し、それをビジターブル クラスの既存のacceptメソッドと組み合わせて使用​​するだけです。2) いくつかの型階層のクラスに対して実行できるアクションが多数ある場合、さまざまなアクションの束に対して一連のメソッドでターゲット クラスを汚染するよりも、各アクションを独自のビジター クラスに分割する方が明確な場合があります。ターゲット クラスではなく、ビジターでグループ化します。

ただし、ほとんどの場合、2 番目の方法、つまり各具象クラスの共通メソッドの定義を単純にオーバーライドする方が簡単です。Entityクラスに抽象draw()メソッドがある場合、エンティティの各タイプはそのメソッドを異なる方法で実装しますdraw()。エンティティの各タイプにdraw()は呼び出すことができるメソッドがあることはわかっていますが、それがどのタイプのエンティティであるか、またはメソッドの実装が何をするかについての詳細を知る必要はありません。あなたがしなければならないのは、あなたを反復してそれぞれList<Entity>を呼び出すことだけです。draw()各タイプには独自の特殊なdraw()実装があるため、タイプに応じて正しいアクションを実行します。

于 2012-08-20T15:01:17.327 に答える
2

インスタンスタイプをチェックしたくない、または機能をチェックするための何らかの機能を持ちたくないのは正しいです。私の最初の質問は、そもそもなぜその基本型のエンティティのリストを持っているのですか? 動的エンティティのリストを維持する必要があるように思えます。

非動的エンティティに対して何もしないメソッドを実装することもできますが、この特定のシナリオでは適切ではないようです。move()

おそらく、そのリストの反復をトリガーするイベントを実装し、そのイベントを各オブジェクトに順番に渡す方がよいでしょう。動的エンティティは、そのイベントに基づいて移動することを決定できます。静的エンティティは明らかにそうではありません。

例えば

   Event ev = ...
   foreach(e : entities) {
      e.actUpon(ev);
   }

このシナリオでは、さまざまなイベント タイプがあり、エンティティはイベント タイプとエンティティ タイプに基づいてアクションを決定します。これは、二重ディスパッチまたは訪問者パターンとして知られています。

于 2012-08-20T14:59:36.050 に答える
1

エンティティの処理がエンティティ タイプに関する詳細を知ることに依存している場合、Entity抽象化はあまり役に立ちません (少なくともこのユース ケースではそうではありませんList<Entity>) List<Object>

想像できるすべてのエンティティが静的または動的であることがわかっている場合、すべてのエンティティにブール型のプロパティを持たせることに「ハードコーディング」する必要はありませんisDynamic()

ただし、動的な側面がエンティティのサブセットに対してのみ意味がある場合、このフラグは確かに抽象化に混乱をもたらします。この場合、私の最初の推測は、それらを処理するのに十分なポリモーフィック情報を提供しないアイテムのリストを操作する必要があるため、ユースケースを適切にモデル化していないということです。

于 2012-08-20T15:02:11.447 に答える