Dove inizializzare gli oggetti

4

Ho una classe BallEntity che fa parte di un gioco che utilizza un'architettura di sistema di componenti Entity.

Questa classe ha 'componenti' che sono come gli attributi di quella classe.
Creo e inizializzo questi componenti nel metodo getComponents. Per costruire questi componenti ho bisogno di altri oggetti, come uno Sprite (ovvero l'immagine rappresenta quella palla) per SpriteComponent, un Body for BodyComponent, una fotocamera per CameraFollowerComponent.
Quegli oggetti arrivano alla classe attraverso argomenti al costruttore.

Istanzio BallEntity in questo modo:

        BallEntity ballEntity = new BallEntity(new Sprite(atlas.findRegion("ball")),rubeSceneHelper.getBody("ball"), camera, rubeSceneHelper);

La mia domanda è se questi oggetti (o quali) devono essere inizializzati nel costruttore di BallEntity o all'interno della classe che istanzia PalEntity?

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));
    }
}
    
posta alexpfx 23.06.2015 - 23:03
fonte

1 risposta

5

Il modo in cui lo stai mostrando ora ("Istanzio il BallEntity in questo modo"), viene eseguito dall'implementazione (codice) che chiama il costruttore per creare BallEntity .

Per essere chiari, il punto è che come lo stai mostrando, ovunque crei un BallEntity (sia in classi separate che in più posti all'interno della stessa classe), stai ri-specificando come creare nuovi oggetti componenti. In altre parole, stai dicendo che è il lavoro del chiamante (creatore di BallEntity ) per identificare e creare i componenti appropriati, ovunque vengano creati questi BallEntity s.

Se esiste solo un luogo in cui viene creato BallEntity , non mi preoccuperei troppo di ciò.

Se si scopre che ci sono più posti nel codice in cui viene creata una BallEntity , dovresti cercare di vedere se ognuno lo fa concettualmente in modo diverso o concettualmente nello stesso modo.

Per la maggior parte dei componenti che vengono creati concettualmente nello stesso modo, allora dovresti applicare i principi DRY (Non ripeterti) e trovare un posto dove inserire questo codice.

Ci sono due alternative che vengono in mente.

(1) Come suggerisci, in BallEntity , inserendo un costruttore addizionale di livello superiore in BallEntity , che prende atlas , rubeSceneHelper e camera come parametri e poi chiama l'altro costruttore usando il codice come suggerito per l'istanziazione di cui sopra. (Forse anche rendere privato il costruttore originale, oppure rimuoverlo e basta avere quello.)

(2) Usa lo schema di progettazione di fabbrica, che dice che hai messo lo stesso codice comune in qualche altra classe di fabbrica. Di solito utilizzi un modello di fabbrica se hai anche ulteriori motivi oltre a quello che mostri qui per disaccoppiare la richiesta di (creazione di) BallEntity e cosa e come viene effettivamente creato.

Ad esempio, con il pattern factory puoi restituire una sottoclasse di BallEntity pari, oppure puoi restituire un Singleton (il pattern di progettazione), oppure, puoi gestire un pool di BallEntity s, e consegnarli basato su qualsiasi tipo di criterio. Mentre con un costruttore puoi solo restituire un nuovo BallEntity ogni volta.

(Infine, se risulta che più classi creano ciascuna istanza BallEntity , e ogni classe istanzia il BallEntity in più punti, tuttavia ogni classe lo considera concettualmente lo stesso internamente a se stesso, ma viene fatto concettualmente in modo diverso tra le classi, quindi l'altro suggerimento è appropriato, per raccogliere quel codice forse una volta in ciascuna di queste altre classi.Questa è una specie di alternativa mista, che sta semplicemente applicando DRY più di una volta, se necessario.)

    
risposta data 24.06.2015 - 03:35
fonte