エンティティコンポーネントシステムアーキテクチャを使用するゲームの一部であるBallEntityクラスがあります。
このクラスには、そのクラスの属性に似た「コンポーネント」があります。
getComponentsメソッドでこのコンポーネントを作成して初期化します。このコンポーネントを作成するには、SpriteComponentのSprite(つまり、画像がそのボールを表す)、BodyComponentのBody、CameraFollowerComponentのカメラなどの他のオブジェクトが必要です。
これらのオブジェクトは、コンストラクターへの引数を介してクラスに到達します。
BallEntityを次のようにインスタンス化します。
BallEntity ballEntity = new BallEntity(new Sprite(atlas.findRegion("ball")),rubeSceneHelper.getBody("ball"), camera, rubeSceneHelper);
私の質問は、これらのオブジェクト(またはどちら)をBallEntityのコンストラクターで初期化する必要があるのか、それともBallEntityをインスタンス化するクラス内で初期化する必要があるのかということです。
public class BallEntity extends UserEntity {
public static final float SCALE = 0.78f;
private final RubeSceneHelper rubeSceneHelper;
private ScaledSprite ballSprite;
private Body ballBody;
private Camera camera;
public BallEntity(Sprite sprite, Body ballBody, Camera camera, RubeSceneHelper rubeSceneHelper) {
this.ballSprite = ScaledSprite.create(Sprite, SCALE / Sprite.getHeight());
this.ballBody = ballBody;
this.camera = camera;
this.rubeSceneHelper = rubeSceneHelper;
}
@Override
public Array<Component> getComponents() {
Array<Component> components = new Array<Component>();
components.add(PositionComponent.newInstance());
components.add(CameraFollowerComponent.newInstance(camera));
components.add(SpriteComponent.newInstance(ballSprite.getSprite()));
components.add(BodyComponent.newInstance(ballBody));
components.add(BallContextComponent.newInstance());
return components;
}
@Override
public void init(Entity entity) {
BodyComponent bodyComponent = entity.getComponent(BodyComponent.class);
bodyComponent.setPosition(Vector2.Zero);
Fixture ballFixture = rubeSceneHelper.getFixture(bodyComponent.getBody(), "ball");
ballFixture.setUserData(new FixtureUserData(FixtureType.BALL, entity));
}
}
現在表示している方法(「この方法でBallEntity
をインスタンス化する」)は、コンストラクターを呼び出してBallEntity
を作成する実装(コード)によって実行されています。
明確にするために、重要なのは、それを表示する方法で、BallEntity
を作成するすべての場所(別々のクラスまたは同じクラス内の複数の場所)で、作成方法を再指定しているということです。新しいコンポーネントオブジェクト。言い換えると、これらのBallEntity
が作成される場所に関係なく、適切なコンポーネントを識別して作成するのは呼び出し元(BallEntity
の作成者)の仕事であると言っています。
BallEntity
が作成される場所が1つしかない場合は、それほど心配する必要はありません。
コード内にBallEntity
が作成される場所が複数あることが判明した場合は、それぞれが概念的に異なる方法で実行されているのか、概念的に同じ方法で実行されているのかを確認する必要があります。
概念的に同じ方法で作成されているコンポーネントの多くについて、DRY(Do n't Repeat Yourself)の原則を適用し、このコードを配置する場所を見つける必要があります。
頭に浮かぶ2つの選択肢があります。
(1)ご提案のとおり、BallEntity
では、BallEntity
に追加の上位レベルのコンストラクターを配置することにより、atlas
、rubeSceneHelper
、およびcamera
をパラメーターとして使用し、上記のインスタンス化で提案したコードを使用して他のコンストラクターを呼び出します。 (元のコンストラクターもプライベートにするか、削除して1つだけにすることもできます。)
(2)ファクトリデザインパターンを使用します。これは、これと同じ共通コードを他のファクトリクラスに配置することを示しています。 BallEntity
(の作成)のリクエストと実際に何をどのように作成するかを分離するためにここに示している以外の理由がある場合は、通常、ファクトリパターンを使用します。
たとえば、ファクトリパターンを使用すると、BallEntity
のサブクラスを返すことも、シングルトン(デザインパターン)を返すことも、BallEntity
sのプールを管理することもできます。あらゆる種類の基準に基づいてそれらを配ります。一方、コンストラクターを使用すると、毎回新しいBallEntity
しか返すことができません。
(最後に、複数のクラスがそれぞれBallEntity
をインスタンス化し、各クラスが複数の場所でBallEntity
をインスタンス化することが判明した場合でも、各クラスはそれ自体の内部で概念的に同じですが、実行されますクラス間で概念的に異なる場合は、他の提案が適切であり、おそらく他の各クラスでそのコードを1回収集します。これは、DRY必要に応じて複数回。)