Java – Factory method pattern in java using generics, how to

design-patternsfactorygenericsjavamethods

I have code that looks like follows:

public interface BaseDAO{
// marker interface
}

public interface CustomerDAO extends BaseDAO{
public void createCustomer();
public void deleteCustomer();
public Customer getCustomer(int id);
// etc
}

public abstract class DAOFactory {
public BaseDAO getCustomerDAO();
public static DAOFactory getInstance(){
  if(system.getProperty("allowtest").equals("yes")) {
  return new TestDAOFactory();
  }
  else return new ProdDAOFactory();
}

public class TestDAOFactory extends DAOFactory{
public BaseDAO getCustomerDAO() {
  return new TestCustomerDAO(); // this is a concrete implementation
  //that extends CustomerDAO
  //and this implementation has dummy code on methods
}

public class ProdDAOFactory extends DAOFactory {
public BaseDAO getCustomerDAO() {
  return new ProdCustomerDAO(); // this implementation would have 
  // code that would connect to the database and do some stuff..
}
}

Now, I do know that this code smells.. for many reasons. However, this code is here too:
http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html, refer 9.8

What I intend to do is this:
1) Switch my DAOs implementations at runtime based on environment (system properties).
2) Make use of java generics so that I can avoid type casting…
for instance does something like this:

CustomerDAO dao = factory.getCustomerDAO();
dao.getCustomer();

As opposed to:

CustomerDAO dao = (CustomerDAO) factory.getCustomerDAO();
dao.getCustomer();

Your thoughts and suggestions, please.

Best Answer

You should define the factory like that:

public abstract class DAOFactory<DAO extends BaseDAO> {
public DAO getCustomerDAO();
public static <DAO extends BaseDAO> DAOFactory<DAO> getInstance(Class<DAO> typeToken){
  // instantiate the the proper factory by using the typeToken.
  if(system.getProperty("allowtest").equals("yes")) {
  return new TestDAOFactory();
  }
  else return new ProdDAOFactory();
}

getInstance should return a proper typed DAOFactory.

The factory variable will have the type:

DAOFactory<CustomerDAO> factory = DAOFactory<CustomerDAO>.getInstance(CustomerDAO.class);

and the usage will be properly typed:

CustomerDAO dao = factory.getCustomerDAO();
dao.getCustomer();

the only problem will probably be a cast required inside the getInstance methods.