I was looking through many approaches to implement a Factory pattern in Java and still couldn't find a perfect one which doesn't suffer from both if/switch plus doesn't use reflection. One of the best that I found was inside Tom Hawtin's answer here: https://stackoverflow.com/a/3434505/1390874
But my biggest concern is that it stores a HashMap of Anonymous classes in a memory.
The question is what do people think about using Class.newInstance() in addition to Tom Hawtin's answer? This will avoid us from storing unnecessary anonymous classes in memory? Plus code will be more clean.
It will look something like this:
class MyFactory {
private static final Map<String,Class> factoryMap =
Collections.unmodifiableMap(new HashMap<String,Class>() {{
put("Meow", Cat.class);
put("Woof", Dog.class);
}});
public Animal createAnimal(String action) {
return (Animal) factoryMap.get(action).newInstance();
}
}
If you are using java 8, you can set up an
enum
like this:You could even have the
enum
implementSupplier<Animal>
and then doAnimalFarm.valueOf("Meow").get();
.Try something like this:
This does not use reflection,
if
, orswitch
, at all.Java 8 introduces some nice lambdas and functional interfaces that makes this really easy. It also avoids a lot of the ugly boilerplate code you would have had to write in previous Java versions. One thing that wasn't immediately clear was how to handle creating objects with constructors that take multiple arguments. Most of Java's functional interfaces allow either one argument or no arguments at all. In this case the solution is to implement your own functional interface.
Imagine your Animal classes all had constructors that looked like this:
You can create a function interface called something like
Factory
in your factory class that has 3 parameters. The first two parameters would be the types of objects you're going to pass to the constructor and the third will be what you're going to return.If all your classes use no-arg constructors then you can drop the custom interface and use something like
Supplier
instead. But everything else should more or less stay the same.