제네릭을 사용하여 Java의 공장 방법 패턴, 방법은?
-
21-08-2019 - |
문제
다음과 같은 것처럼 보이는 코드가 있습니다.
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 방법 내에서 필요한 캐스트 일 것입니다.
다른 팁
필요한 것을 자세히 설명하는 기사가 많이 있습니다.
- JDK 5.0의 일반 DAO 패턴
- 일반 데이터 액세스 개체 (같은 상기와)
- DAO를 반복하지 마십시오 (봄이지만 원칙은 동일합니다)
- Java 1.5 일반 DAO (다시 봄)
예와 달리 방법이 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에 가까운 것을 반환하지 않는 경우 (구현의 변경으로 인해) 이것은 나에게 더 깨끗해 보인다.
내 두 센트.