문제

다음과 같은 것처럼 보이는 코드가 있습니다.

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) 환경 (시스템 속성)을 기반으로 런타임에서 DAOS 구현을 전환하십시오. 2) 유형 주조를 피할 수 있도록 Java 제네릭을 사용하십시오. 예를 들어 다음과 같은 작업을 수행하십시오.

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

반대로 :

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

당신의 생각과 제안, 제발.

도움이 되었습니까?

해결책

공장을 다음과 같이 정의해야합니다.

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<CustomerDAO> factory = DAOFactory<CustomerDAO>.getInstance(CustomerDAO.class);

그리고 사용법은 올바르게 입력됩니다.

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

유일한 문제는 아마도 GetInstance 방법 내에서 필요한 캐스트 일 것입니다.

다른 팁

필요한 것을 자세히 설명하는 기사가 많이 있습니다.

예와 달리 방법이 DAOFactory 실제 서브 클래스를 반환해서는 안됩니다 (즉 CustomerDAO getCustomerDAO()). 또한 일반 DAO를 사용하는 주요 이점은 엔티티 유형의 "일반화"가 있으므로 캐스트 할 필요가 없습니다. load()/get()/find() 그리고 비슷한 방법.

귀하의 예는 필요를 보여주지 않습니다 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() {
    ...
  }
}

나는 여러 프로젝트 에서이 접근법과 같은 것을 사용했으며 모델의 모든 엔티티에서 작동하는 하나의 DAO를 작성하는 것이 매우 좋습니다. 약점은 "파인더"방법입니다. 몇 가지 깔끔한 접근법이 있으며, JPA의 다가오는 작업은 "기준"API를 표준화하고 있지만 현재는 기본 지속 메커니즘의 기준을 노출시키는 것이 가장 쉽습니다.

공장을 사용했을 때 일반적으로 인스턴스를 사용하여 실제 유형의 객체를 결정했습니다. 예를 들어:

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

특히 Factory.getCustomerDao ()가 CustomerDAO에 가까운 것을 반환하지 않는 경우 (구현의 변경으로 인해) 이것은 나에게 더 깨끗해 보인다.

내 두 센트.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top