java中使用泛型的工厂方法模式,如何?

Jay*_*Jay 5 java generics methods design-patterns factory

我的代码如下所示:

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..
}
}
Run Code Online (Sandbox Code Playgroud)

现在,我知道这段代码闻起来有很多原因.但是,此代码也在这里:http: //java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html,请参阅9.8

我打算这样做:1)根据环境(系统属性)在运行时切换我的DAO实现.2)使用java泛型,以便我可以避免类型转换...例如,做这样的事情:

CustomerDAO dao = factory.getCustomerDAO();
dao.getCustomer();
Run Code Online (Sandbox Code Playgroud)

相反:

CustomerDAO dao = (CustomerDAO) factory.getCustomerDAO();
dao.getCustomer();
Run Code Online (Sandbox Code Playgroud)

请你的意见和建议.

Mih*_*der 10

您应该像这样定义工厂:

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();
}
Run Code Online (Sandbox Code Playgroud)

getInstance应该返回一个正确的类型DAOFactory.

工厂变量将具有以下类型:

DAOFactory<CustomerDAO> factory = DAOFactory<CustomerDAO>.getInstance(CustomerDAO.class);
Run Code Online (Sandbox Code Playgroud)

并且将正确输入用法:

CustomerDAO dao = factory.getCustomerDAO();
dao.getCustomer();
Run Code Online (Sandbox Code Playgroud)

唯一的问题可能是getInstance方法中需要的强制转换.


jav*_*ook 6

有一堆文章详细说明了你的需求:

请注意,与您的示例不同,没有理由DAOFactory不应该返回实际的子类(即CustomerDAO getCustomerDAO()).此外,使用通用DAO的主要好处是使实体类型为"通用化",因此您不必使用load()/get()/find()类似方法进行转换.


eri*_*son 5

您的示例并未证明需要BaseDAO,并且没有理由DAOFactory.getCustomerDAO()不应声明为什么不返回CustomerDAO.所以,我并不认为那里需要仿制药.但是,请考虑以下事项:

interface DataAccess<T> {
  void store(T entity);
  T lookup(Serialiable identifier);
  void delete(Serializable identifier);
  Collection<? extends T> find(Criteria query);
}

abstract class DataAccessFactory {
  abstract DataAccess<T> getDataAccess(Class<T> clz);
  static DataAccessFactory getInstance() {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

我在几个项目中使用了类似这种方法的东西,编写一个适用于模型中每个实体的DAO非常好.弱点是"发现者"方法.有一些巧妙的方法,JPA即将开展的工作是标准化"Criteria"API,但是现在通常最容易公开底层持久性机制的标准.