Using Enum for factory in Java, a best practice?

airdump picture airdump · Jul 10, 2013 · Viewed 30.3k times · Source

Java allow us to embed data and behaviour on Enum. I don't want to implement a factory directly on an Enum, because I think this is not its role.

But I can put class reference on the enum, and contruct object on an external factory. Comparing to a traditionnal factory pattern, what is the best implementation for you ? Which solution is better to use in which case ?

Now, the code.

Function used in both solutions to construct objects. Usefull to implement fly-weight pattern with a Map if required.

private Action getAction(Class<? extends Action> actionClazz) {
    // logger + error handling
    return actionClazz.newInstance();
}

1) With a traditionnal factory:

public enum ActionEnum {
    LOAD_DATA,
    LOAD_CONFIG;
}

public Action getAction(ActionEnum action) {
    switch (action) {
    case LOAD_CONFIG:
        return getAction(ActionLoadConfig.class);
    case LOAD_DATA:
        return getAction(ActionLoadData.class);
    }
}

2) With Enum-styled factory :

public enum ActionEnum {
    LOAD_DATA(ActionLoadConfig.class),
    LOAD_CONFIG(ActionLoadData.class);

    public ActionEnum(Class<? extends Action> clazz){...}
    public Class<? extends Action> getClazz() {return this.clazz}
}

public Action getAction(ActionEnum action) {
    return getAction(action.getClazz());
}

Answer

JB Nizet picture JB Nizet · Jul 10, 2013

The second one is much cleaner: it doesn't need any long switch block, and has 0 risk of forgetting one of the enum values like the first one has.

It's not always possible to use it, though, because the enum might be some generic enum (Month, for example), that should not be coupled to the factory of actions.