Instanciate an object depending on a variable value
Hi there,
I am developing a Web application based on a JSP+persistency MVC framework. In a number of classes, I have to be able to instanciate a "model" object (OO mapping from an RDBMS table) whose type depends on the value of a String variable. Currently, this is done this way:
if(Constants.CONSTANT1.equals(value)){
returnnew Type1Model(args);
}elseif(Constants.CONSTANT2.equals(value)){
returnnew Type2Model(args);
}// else if...
The Type1Model, Type2Model, etc. classes extend the same base class. But I find this code ugly - while quite efficient.
So I am trying to come to a design in which I call ModelFactory.getModel(value, args), period (more accurately, semi-colon). This factory holds a Hashtable, mapping possibles values for "value" to Class. Thus, each Type*Model class registrers itself in the ModelFactory for a given value, guaranteeing simple extensibility without modifying the factory nor the code that uses it.
Now, am I complicating a lot too much this task which is so easy to perform in C-style code ? Or is this the path to OO-enlightenment ?
Thanks and regards.
[1533 byte] By [
Elessaera] at [2007-10-3 2:18:39]

In my opinion a map is a better idea than a bunch of else if statements.
This might be overkill or might not be useful in your situation but you could take that idea further and add a table in the database that would map these values to the class names and then use Reflection to create instances.
This would allow you to handle new values without touching the code.
zadoka at 2007-7-14 19:17:33 >

> Now, am I complicating a lot too much this task which
> is so easy to perform in C-style code ? Or is this
> the path to OO-enlightenment ?
This is a valid and very powerful implementation of an Abstract Class factory. I've used Properties files and XML files to configure my factories inthis way.
A similar approach is used extensively in Tomcat, checkout a server.xml file; where a classesName attribute appears in a tag you have a softcoded factory e.g. Realms, DataSource and Connections.
I would in general avoid the if's as doing a more flexible approach is just as easy to code and more flexible.
It is always best to first focus on the way you would like to call your code and then work on the details of what you need to do to get the code working (i.e. focus on the interface first).
You could use reflection and pass in the class name you would like to construct, and simply use the class name as your constant. This is very simple and flexible. The following is close although I didn't test it.
A sample invocation would be:
Model myModel=ModelFactory.getModel("com.ssouza.MyModel", args);
public class ModelFactory {
public static Model getModel(String className, Object[] args) {
// this is more psuedo code and I don't know the exact syntax, but
Class cls=Class.forName(className);
Class[] argTypes=loop through args array getting the Class associated with each and put it into this Class array
Constructor con=cls.getConstructor(argTypes);
return (Model) con.newInstance(args);
}
}
Steve http://www.jamonapi.com - JDBC/SQL monitoring in jamon 2.3!