I am working on a very simple game and thought it would be a good opportunity to learn and use the Factory Method pattern for creating game objects. I studied the pattern but I'm a bit confused about the Java implementation so thought I would share what I have come up with and get some opinions.
Please keep in mind that I am basing this design on the example from "Design Patterns... by the GOF" so we will use the following pieces: Product, ConcreteProduct, Creator, and ConcreteCreator.
Product (Interface for Game Objects)
public interface GameObject {
public abstract void doSomeStuff();
}
ConcreteProducts (Implements Product Interface, 1 for each Game Object)
public class PlayerImpl implements GameObject {
@Override
public void doSomeStuff() {
System.out.println("I am a player object!");
}
}
public class EnemyImpl implements GameObject {
@Override
public void doSomeStuff() {
System.out.println("I am an Enemy, you better run!");
}
}
Creator (Interface that defines how to create objects)
This is the one I'm most confused about, seems un-necessary unless instead of an Interface it was some Abstract class, but even then seems kind of pointless to use a Creator in this design pattern?
public interface GameObjectFactory {
public abstract GameObject createGameObject(GameObjectFactoryImpl.Type type);
}
ConcreteCreator (Implements Creator, creates objects)
The ConcreteCreator will have a nested enumeration to help the client decide which player types are available. We will throw an exception if for some reason there is a game object type in the enumeration that is not handled in the factory method.
public class GameObjectFactoryImpl implements GameObjectFactory{
// A helper enum that clients will use to create game objects
public enum Type {
PLAYER, ENEMY;
}
public GameObject createGameObject(GameObjectFactoryImpl.Type type) {
switch (type) {
case PLAYER:
return new PlayerImpl();
case ENEMY:
return new EnemyImpl();
default:
throw new RuntimeException("Unsupported object type!");
}
}
}
Client
public class Game {
private static GameObjectFactory gameObjectFactory = new GameObjectFactoryImpl();
public static void main(String args[]){
GameObject player = gameObjectFactory.createGameObject(GameObjectFactoryImpl.Type.PLAYER);
GameObject enemy = gameObjectFactory.createGameObject(GameObjectFactoryImpl.Type.ENEMY);
player.doSomeStuff();
enemy.doSomeStuff();
}
}
new PlayerImpl()
is what actually happens when there's a new player. That's way less code thangameObjectFactory.createGameObject(GameObjectFactoryImpl.Type.PLAYER);
- ask yourself what are you gaining by adding this. Usually, you want to apply this pattern when the code to create the object is complex (and so it's encapsulated in the factory method). Your example doesn't suffer from the problem this pattern solves. \$\endgroup\$