What you've done is probably the best way to go about it, until a switch on string is available. (Edit 2019: A switch on string is available - use that.)
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();
}
At the time this answer was originally written, the features intended for JDK7 could make the code look as below. As it turned out, lambdas appeared in Java SE 8 and, as far as I am aware, there are no plans for map literals. (Edited 2016)
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 2019: Currently this would look something like this.
import java.util.function.*;
import static java.util.Map.entry;
private static final Map<String,Supplier<Animal>> factoryMap = Map.of(
"Meow", Cat::new, // Alternatively: () -> new Cat()
"Woof", Dog::new // Note: No extra comma like arrays.
);
// For more than 10, use Map.ofEntries and Map.entry.
private static final Map<String,Supplier<Animal>> factoryMap2 = Map.ofEntries(
entry("Meow", Cat::new),
...
entry("Woof", Dog::new) // Note: No extra comma.
);
public Animal createAnimal(String action) {
Supplier<Animal> factory = factoryMap.get(action);
if (factory == null) {
throw EhException();
}
return factory.get();
}
If you want to add a parameter, you'll need to switch Supplier
to Factory
(and get
becomes apply
which also makes no sense in the context). For two parameters BiFunction
. More than two parameters, and you're back to trying to make it readable again.