Eu uso o design pattern DAO com a estratégia de fábrica abstrata desde que me entendo por gente.
Fiz a seguinte modificação na implementação demonstrada no catálogo de padrões J2EE:
- Inicializar o objeto de conexão, com o repositório de dados, na inicialização da fábrica concreta.
- Passar o objeto de conexão, com o repositório, pelo construtor das implementações(deste repositório) das interfaces DAOs.
- Deslocar para o usuário, do DAO, a responsabilidade de criar e terminar uma transação ao executar seus métodos. Isto é feito à partir da DAOFactory, que possui métodos para controle transacional dos DAOs criados por ela.
Tenho usado essa implementação sem problemas há, aproximadamente, 2 anos.
Mas considero insuportável escrever os métodos abstratos(na fábrica abstrata) para retornar a implementação do DAO e ainda ter que escrever a implementação destes métodos em cada fábrica concreta. Implementação esta que consiste apenas em dar um new em uma classe e colocar o objeto de conexão com o repositório no construtor.
Neste feriado, eu resolvi dar um fim nesses métodos.
O desafio era fazer isso sem perder a checagem feita pelo compilador se a classe DAO que eu estou retornando implementa a interface DAO que eu estou querendo usar.
E para isso comecei definindo algumas convenções:
- O nome da interface DAO será o nome da entidade com o sufixo DAO. Por exemplo, o DAO para a entidade Cliente será ClienteDAO;
- O pacote, onde ficam as interfaces e a fábrica abstrata será assim: pacote.do.sistema.dao;
- O nome da implementação da interface DAO será o nome da interface DAO com o prefixo do repositório. Por exemplo, a implementação usando JPA será: JpaClienteDAO;
- O pacote, onde ficam a implementação e a fábrica concreta, será um sub-pacote, do pacote onde estão as interfaces e a fábrica abstrata, como em: pacote.do.sistema.dao.jpa;
Essas convenções me permitiram modificar a fábrica abstrata para retornar a implementação de uma interface DAO a partir da interface DAO.
Esta “mágica” é feita pelo método getDao:
public <T extends CrudDAO> T getDao(Class<T> daoInterface) thrws DAOException{ |
Mas ainda preciso saber o prefixo das implementações. Para resolver isso criei um método, na fábrica abstrata, que retorna uma String. Esta String é o prefixo da implementação, que a fábrica concreta, irá informar.
Na fábrica abstrata, isto é, a classe DAOFactory:
protected abstract String getPrefixoImpl(); |
E a implementação na fábrica concreta usando a JPA, isto é, JpaDAOFactory:
@Override return "jpa"; |
Eu tenho uma classe base para os meus DAOs, que implementam as operações básicas de inclusão, alteração, exclusão e busca da entidade, e tem um contrutor que recebe o EntityManager a ser usado nestas operações.
Por conta deste contrutor eu preciso dos métodos getRepositoryTypes() e o getRepositoryArgs que irão retornar o objeto responsável pelo acesso ao banco de dados(EntityManager no caso do JPA, Session no caso de Hibernate e Connection no caso de JDBC “cru”).
Com essas alterações simples eu posso recuperar a implementação do DAO sem precisar criar um método para cada DAO em cada implementação da fábrica abstrata.
E para usar a nova implementação, o código fica assim:
DAOFactory factory = DAOFactory.getInstance();
EntidadeDAO dao = factory.getDao(EntidadeDAO.class);
Faça o download do projeto, para Eclipse, que tem a implementação de tudo o que eu escrevi até aqui.
Por restrições do WordPress eu tive que renomear a extensão do arquivo para “pdf”, basta trocar por “zip” que você irá conseguir descompactá-lo.
Para usá-lo:
- Importe o projeto para o seu eclipse;
- Coloque o driver para o banco de dados e adicione-o ao class-path do projeto;
- Configure o arquivo persistence.xml na pasta META-INF com os dados da conexão ao seu banco;
- Execute a classe ExemploMain.
Sugestões serão bem vindas. E analisadas, caso eu concorde coloco no exemplo e atualizo ele.
Po-por hoje é só pe-pe-ssoal. =D
Escrito por AC de Souza