I am trying to find a easy to extend way to create objects at runtime based on a static String class attribute, called NAME.
How can I improve this code, which uses a simple if construct?
public class FlowerFactory {
private final Garden g;
public FlowerFactory(Garden g) {
this.g = g;
}
public Flower createFlower(final String name) {
Flower result = null;
if (Rose.NAME.equals(name)) {
result = new Rose(g);
} else if (Oleander.NAME.equals(name)) {
result = new Oleander(g);
} else if ... { ... } ...
return result;
}
newInstance() can not be used on these classes, unless I remove the constructor argument. Should I build a map (Map) of all supported flower class references, and move the contructor argument to a property setter method, or are there other simple solutions?
Background information: my goal is to implement some kind of 'self-registering' of new Flower classes, by FlowerFactory.getInstance().register(this.NAME, this.class)
, which means that from the very good answers so far the introspection-based solutions would fit best.
You can use reflection despite having a constructor argument:
Rose.class.getConstructor(Garden.class).newInstance(g);
Combined with a static name to class mapping, this could be implemented like this:
// TODO handle unknown name
FLOWERS.get(name).getConstructor(Garden.class).newInstance(g);
where flowers could be populated in a static initializer block:
static {
Map<String, Class<? extends Flower>> map = new HashMap<String, Class<? extends Flower>>();
map.put(Rose.NAME, Rose.class);
// add all flowers
FLOWERS = Collections.unmodifieableMap(map);
}