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

Viewed 30025

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?

10 Answers

Now you could use Java 8 constructor references and a functional interface.

import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

public class AnimalFactory {
    static final Map<String, Supplier<Animal>> constructorRefMap = new HashMap<>();

    public static void main(String[] args) {
        register("Meow", Cat::new);
        register("Woof", Dog::new);

        Animal a = createAnimal("Meow");
        System.out.println(a.whatAmI());
    }

    public static void register(String action, Supplier<Animal> constructorRef) {
        constructorRefMap.put(action, constructorRef);
    }

    public static Animal createAnimal(String action) {
        return constructorRefMap.get(action).get();
    }
}

interface Animal {
    public String whatAmI();
}

class Dog implements Animal {
    @Override
    public String whatAmI() {
        return "I'm a dog";
    }
}

class Cat implements Animal {
    @Override
    public String whatAmI() {
        return "I'm a cat";
    }
}
Related