Pergunta

Eu tenho o código que se parece com a seguir:

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

Agora, eu sei que este código cheira .. por muitas razões. No entanto, este código também está aqui: http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html , consulte 9.8

O que eu pretendo fazer é esta: 1) Mudar meus DAOs implementações em tempo de execução com base no ambiente (propriedades do sistema). 2) Fazer uso de genéricos Java para que eu possa evitar tipo de fundição ... por exemplo, faz algo parecido com isto:

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

Ao contrário:

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

Seus pensamentos e sugestões, por favor.

Foi útil?

Solução

Você deve definir a fábrica assim:

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 deve retornar um DAOFactory digitado adequada.

A variável fábrica terá o tipo:

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

eo uso será devidamente digitado:

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

O único problema será, provavelmente, um elenco exigida dentro dos métodos getInstance.

Outras dicas

Há um monte de artigos detalhando o que você precisa:

Por favor note que, ao contrário de seu exemplo, não há nenhuma razão para que os métodos de DAOFactory não deve retornar as subclasses reais (ou seja CustomerDAO getCustomerDAO()). Além disso, a principal vantagem de usar DAOs genéricos é ter o tipo de entidade "genericized", assim você não precisa se fundido a partir de métodos load()/get()/find() e similares.

Seu exemplo não demonstrar uma necessidade de BaseDAO, e não há nenhuma razão para que DAOFactory.getCustomerDAO() não deve ser declarado para retornar um CustomerDAO. Então, eu realmente não vejo a necessidade de genéricos lá. No entanto, considere o seguinte:

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() {
    ...
  }
}

Eu usei algo como esta abordagem em vários projectos, e é muito bom para escrever um DAO que funciona para cada entidade do modelo. A fraqueza é os métodos "Finder". Há algumas abordagens de bom gosto, e próximo trabalho em JPA está padronizando a API "Critérios", mas por agora é muitas vezes mais fácil de expor os critérios do mecanismo de persistência subjacente.

Quando eu tenho fábricas usados ??Eu normalmente usado instanceof para determinar o verdadeiro tipo do objeto. Por exemplo:

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

Isso só parece mais limpo para mim, especialmente se factory.getCustomerDAO () não retorna nada perto de uma CustomerDAO (devido a alterações na implementação).

Apenas meus dois centavos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top