Brad Brad - 4 months ago 8
Java Question

Creating a factory method in Java that doesn't rely on if-else

Currently I have a method that acts as a factory based on a given String.
For example:

public Animal createAnimal(String action)
{
if (action.equals("Meow"))
{
return new Cat();
}
else if (action.equals("Woof"))
{
return new Dog();
}

...
etc.
}


What I want to do is avoid the entire if-else issue when the list of classes grows.
I figure I need to have two methods, one that registers Strings to classes and another that returns the class based on the String of the action.

What's a nice way to do this in Java?

Answer

What you've done is probably the best way to go about it, until a switch on string is available.

You could create factory objects and a map from strings to these. But this does get a tad verbose in current Java.

private interface AnimalFactory {
    Animal create();
}
private static final Map<String,AnimalFactory> factoryMap =
    Collections.unmodifiableMap(new HashMap<String,AnimalFactory>() {{
        put("Meow", new AnimalFactory() { public Animal create() { return new Cat(); }});
        put("Woof", new AnimalFactory() { public Animal create() { return new Dog(); }});
    }});

public Animal createAnimal(String action) {
    AnimalFactory factory = factoryMap.get(action);
    if (factory == null) {
        throw new EhException();
    }
    return factory.create();
}

In JDK8 this may look something like:

private interface AnimalFactory {
    Animal create();
}
private static final Map<String,AnimalFactory> factoryMap = {
    "Meow" : { -> new Cat() },
    "Woof" : { -> new Dog() },
};

public Animal createAnimal(String action) {
    AnimalFactory factory = factoryMap.get(action);
    if (factory == null) {
        throw EhException();
    }
    return factory.create();
}

[edit: lambdas were introduced in JDK8, not JDK7.]

Comments