I have a design question to ask. I so far have not written any code, just thinking about how to implement at this point. I have an object of type A and it contains an object of type B. I would like B to define a category of objects (Interface or abstract class?). I then have an xml file that defines the sub-type that B should be. For instance, if B is an interface named Driveable, then "car" or "truck" might be defined in the xml as the Drivable object needed for type A.
What I was thinking of doing is making B an interface and then creating a static factory class that has a factory method to determine what sub-type B should be given an xml file. So my first question is would this be the best way to approach the problem? Would it be better to use an abstract class instead of an interface or is it mainly just personal preference?
Second, if I do go with an interface, then inside my factory method would I just do:
B createB(File f){
...
String type = ...
if(type.equals("car"))
return new CarType();
else if(type.equals("truck"))
return new TruckType();
...
return null;
}
So every time I add a new B sub-type, I would need to add another if statement to this method. Is there a better way to do this so all I would have to do is create a new B sub-type and then update my xml and not update the factory method? I essentially dont want to hard code in the types of B into my factory method. If what I have above is pretty standard protocol with factory methods, then I can deal with doing it that way, just doesnt quite seem right.
Growing off of carnold's example, your could create a map in your Factory Class that maps between the text in the xml and the corresponding java class.
private final static Map<String, Class> typeMap;
static {
typeMap = new HashMap<String, Class>();
typeMap.put("car", CarType.class);
typeMap.put("truck", TruckType.class);
}
and then in your method:
B createB(File f){
...
String type = ...
Class clazz = typemap.get(type);
if (clazz == null){
return null;
}
B newB = clazz.getConstructor(/*arg types*/).newInstance(/*args*/);
return newB;
}
Slightly easier to maintain than the if/else, but still have to maintain it.