5

我的代码如下所示:

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..
}
}

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

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

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

相对于:

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

请提出您的想法和建议。

4

4 回答 4

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();
}

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

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

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

并且用法将被正确输入:

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

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

于 2009-05-13T18:48:36.387 回答
6

有很多文章详细说明了您的需求:

请注意,与您的示例不同,方法没有理由DAOFactory不返回实际的子类(即CustomerDAO getCustomerDAO())。此外,使用泛型 DAO 的主要好处是实体类型“泛型化”,因此您不必转换 fromload()/get()/find()和类似的方法。

于 2009-05-12T23:21:26.887 回答
5

您的示例没有证明需要BaseDAO,并且没有理由DAOFactory.getCustomerDAO()不应该声明返回 a 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() {
    ...
  }
}

我在几个项目中使用过类似的方法,编写一个适用于模型中每个实体的 DAO 非常好。弱点是“查找器”方法。有一些巧妙的方法,JPA 中即将开展的工作是标准化“Criteria”API,但现在公开底层持久性机制的标准通常是最容易的。

于 2009-05-12T23:24:05.870 回答
0

当我使用工厂时,我通常使用 instanceof 来确定对象的真实类型。例如:

CustomerDAO dao;
if (factory.getCustomerDAO() instanceof CustomerDAO) {
   dao = factory.getCustomerDAO();
}
dao.getCustomer();

这对我来说似乎更干净,特别是如果 factory.getCustomerDAO() 没有返回任何接近 CustomerDAO 的东西(由于实现的变化)。

只是我的两分钱。

于 2009-05-12T23:20:14.207 回答