Ziamor
Ziamor

Reputation: 533

How to create an object by pulling the type from a variable?

I've been working on a level reader in Java that pulls the level data from an XML document for my game. Everything's been going fine however I have hit an issue. One thing I'm pulling from the document is the ID of the game object to create. I have a bunch of classes such as wall,player and coin all of which extend a GameObject class. I want to have a method in the GameObject class that returns a GameObject based on the ID. Something like this:

public GameObject CreateGameObject(int id, int x, int y, GameScreen parent) {
    Type type = getTypeFromList(id);
    Type gobj = new Type(x,y,parent);
    return gobj;
}

I know I can do this using a bunch of if statements checking the ID and returning the correct one but I want the code to be clean and more versatile. If you could please help show me how to do this or show me another way that would be very much appreciated.

Upvotes: 0

Views: 106

Answers (1)

Paul Bellora
Paul Bellora

Reputation: 55213

I would suggest using a factory interface for GameObject creation, with an implementation for each type (like arynaq mentioned in the comments):

interface GameObjectFactory {
    GameObject create(); // this could also take arguments like x, y, and parent
}

private static final Map<Integer, GameObjectFactory> FACTORIES_BY_ID;
static {
    final Map<Integer, GameObjectFactory> factoriesById = new HashMap<>();

    // ID 42 is for walls
    factoriesById.put(42, new GameObjectFactory() {
        @Override
        public GameObject create() {
            return new Wall();
        }
    });

    //etc.

    FACTORIES_BY_ID = factoriesById;
}

You could also use an array if the IDs are sequential:

private static final GameObjectFactory[] FACTORIES = {
    // ID 0 is for walls
    new GameObjectFactory() {
        @Override
        public GameObject create() {
            return new Wall();
        }
    }
};

An enum could work too:

enum GameObjectFactory {

    WALL(42) {
        @Override
        GameObject create() {
            return new Wall();
        }
    };

    private final int id;

    private GameObjectFactory(int id) {
        this.id = id;
    }

    abstract GameObject create();

    static GameObjectFactory getById(int id) {
        for (GameObjectFactory factory : values()) {
            if (factory.id == id) {
                return factory;
            }
        }
        throw IllegalArgumentException("Invalid ID: " + id);
    }
}

Upvotes: 1

Related Questions