Factory Method

10 respostas
bruno_SI

Bom dia pessoal, estou criando uma aplicação simples para uma disciplina da faculdade.
Resolvi implementar alguns Design Patterns. Ao tentar implementar Factory Method para me retornar a instancia de um novo objeto criado
encontrei dificuldades.

Na Bean fiz assim

public void Salvar(){
        
        Funcionario F = new Funcionario();
        F.setCargo("Diretor Comercial");
        F.setLogin("administrador");
        F.setSenha("123");
        F.setNivel(1);
        
        IFuncionario dao = FactoryDAO.creatObject("FuncionarioDAO");
        dao.Salvar();
    }

Meu problema está ali na implementação desse método que me retornará o objeto criado. No caso, um objeto da Classe FuncionarioDAO.
Qual seria a forma correta de ser fazer isso? Pensei em criar um método que receba um parâmetro, no caso acima passei uma string com
o nome da classe, dentro do método faço um switch e instancio o objeto de acordo com esse parametro. Seria correto?

Agradeço a ajuda desde já.

10 Respostas

ivandasilva

Acho que uma solução simples para você seria passar uma Class<?> e instanciar o objeto por reflection, tipo

IFuncionario createObject(Class<? extends IFuncionario> obj) throws InstantiationException, IllegalAccessException { return (IFuncionario) obj.newInstance();}

Agora se os construtores das classes receberem parâmetros, é legal você trabalhar cada objeto. Geralmente se tem uma fábrica de objetos para a fábrica fazer o trabalho difícil de criar objetos, mas, neste caso, esta simples, não sei se há a necessidade de uma factory.

bruno_SI

Agradeço a ajuda Ivan, me desculpe pela ignorância mais estou iniciando em java e não compreendi a sintaxe acima.
Realmente o fabrica não seria necessária neste simples sistema, porém ela é um requisito do trabalho.

ivandasilva

Então eu acho melhor você fazer o Java “puro”, igual é na facul…

enum TipoFuncionario{

Diretor, Merendeira, Professor;

}



IFuncionario creatObject(TipoFuncionario tipo){

    if(tipo == TipoFuncionario.Diretor){
          return(IFuncionario) new Diretor();
   } else if .....................

}
bruno_SI

Perfeito Ivan
Funcionou belezinha aqui.
Grato pela ajuda.

ivandasilva

bruno_SI, põe o tópico como resolvido.
Vlw

bruno_SI

Acabei de crê. Sou nob mesmo…rsrsrs
onde marco o tópico como respondido? :lol:

Leandro_Rocha

Olá
Aproveitando o embalo, estava procurando na internet algo sobre Factory Method e Abstract Method aplicados com DAOs, e encontrei esse artigo:
[url]http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html[/url]
Porém, para a fábrica abstrata eles utilizam uma classe abstrata (que inclusive pode ser substituída por um interface), eu não queria ficar utilizando herança e pensei por trocar a classe abstrata por uma interface.

Como meu sistema é simples, não envolve muitos cadastros, tabelas etc, encontrei duas formas de implementação desses patterns com DAO.
Vou postar o código e me digam se este jeito de fazer é "feio" ou não :roll:

Fábrica abstrata (DAOFactory):

package Model.DAO;

/**
 *
 * @author Leandro
 */
public interface DAOFactory {
    public BairroDAO createBairroDAO();
    public CategoriaCursoDAO createCategoriaCursoDAO();
    //... Demais assinaturas de métodos etc...
}
Agora a fábrica concreta para DAOs utilizando persistência com JDBC (JDBCDAOFactory):
package Model.DAO;

/**
 *
 * @author Leandro
 */
public class JDBCDAOFactory implements DAOFactory {

    @Override
    public BairroDAO createBairroDAO() {
        return new JDBCBairroDAO();
    }
    
    @Override
    public CategoriaCursoDAO createCategoriaCursoDAO() {
        return new JDBCCategoriaCursoDAO();
    }
}
Um seletor de fábricas (um exemplo), caso se queira trabalhar com mais de um tipo de persistência (Como XML, Hibernate, etc...) (FactorySelector):
package Model.DAO;

/**
 *
 * @author Leandro
 */
public final class FactorySelector {
    public enum Implementacao {
        JDBC,
        XML,
        HIBERNATE;
    }
    /**
     * Método para escolha da fábrica concreta.
     * @param impl Tipo de persistência a ser utilizada.
     * @return A fábrica concreta para criação dos objetos de persistência.
     */
    public static DAOFactory createDAOFactory(Implementacao impl) {
        switch(impl) {
            case JDBC:
                //Existe implementação para persistência utilizando JDBC:
                return new JDBCDAOFactory();
            case XML:
                //Não existe implementação de persistência com XML no momento.
                throw new UnsupportedOperationException("Não há implementação para persistência com XML.");
            case HIBERNATE:
                 //Não existe implementação de persistência utilizando Hibernate no momento.
                throw new UnsupportedOperationException("Não há implementação para persistência com Hibernate.");
            default: 
                throw new IllegalArgumentException("Tipo de persistência desconhecida ou não suportada.");
        }
    }
}

Implementei desse modo tendo como modelo as práticas desse outro artigo em que a classe abstrata foi substituída por uma inteface:
[url]http://www.javapractices.com/topic/TopicAction.do?Id=128[/url]
É a única diferença entre os dois artigos praticamente, além de algumas implementações extras.

Porém, não sei se estou errado, ou criando um anti-pattern, mas achei essa questão de criar uma DAOFactory e depois uma JDBCDAOFactory, XMLDAOFactory, ou HibernateDAOFactory, meio que reduntante, então coloquei as decisões de que implementação de DAO retornar em uma única classe, vejam: "Fábrica única" (DAOFactoryUnica):
package Model.DAO;

/**
 *
 * @author Leandro
 */
public class DAOFactoryUnica {
    public enum Implementacao {
        JDBC,
        XML,
        HIBERNATE;
    }
    
    public BairroDAO createBairroDAO(Implementacao impl) {
        if(impl == Implementacao.JDBC) {
            //Existe implementação para persistência utilizando JDBC:
            return new JDBCBairroDAO();
        }
        
        else if (impl == Implementacao.XML) {
            //Não existe implementação de persistência com XML no momento.
            throw new UnsupportedOperationException("Não há implementação para persistência com XML.");
            //Se houver implementação será:
            //return new XMLBairroDAO;
        }
        
        else if(impl == Implementacao.HIBERNATE) {
             //Não existe implementação de persistência utilizando Hibernate no momento.
             throw new UnsupportedOperationException("Não há implementação para persistência com Hibernate.");
             //Se houver implementação será:
             //return new HibernateBairroDAO;
        }
        
        else {
            throw new IllegalArgumentException("Tipo de persistência desconhecida ou não suportada.");
        }
    }
    
    public CategoriaCursoDAO createCategoriaCursoDAO(Implementacao impl) {
        if(impl == Implementacao.JDBC) {
            //Existe implementação para persistência utilizando JDBC:
            return new JDBCCategoriaCursoDAO();
        }
        
        else if (impl == Implementacao.XML) {
            //Não existe implementação de persistência com XML no momento.
            throw new UnsupportedOperationException("Não há implementação para persistência com XML.");
            //Se houver implementação será:
            //return new XMLCategoriaCursoDAO;
        }
        
        else if(impl == Implementacao.HIBERNATE) {
             //Não existe implementação de persistência utilizando Hibernate no momento.
             throw new UnsupportedOperationException("Não há implementação para persistência com Hibernate.");
             //Se houver implementação será:
             //return new HibernateCategoriaCursoDAO;
        }
        
        else {
            throw new IllegalArgumentException("Tipo de persistência desconhecida ou não suportada.");
        }
        
        //... Criação dos demais objetos...
    }
}

Gostaria da opnião e sugestões de vocês, o que acham desse modelo, está errado, pode ser implementado e/ou melhorado?
Obrigado pessoal :)

Leandro_Rocha

?? :roll:

ivandasilva

Bom, eu não sou expert no assunto, mas, posso dizer que funcionar funciona, mas não é muito legal não, isto porque no seu lab, você tem poucas DAOs para criar, imagine em um sistema corporativo real. Além que na sua alternativa o seu código fica mais acoplado do que no outro. Pensando além, em qualidade de código, dizem que não é muito bom ter uma classe com tantas linhas rsrsrsrs… ferramentas que garantem qualidade de código reclamam de classes com muitas linhas…

Leandro_Rocha

É verdade amigo…
Eu repensei, aqui, não é legal mesmo implementar desse segundo modo ai, pensei que estava fazendo algo legal mas estava era fugindo da orientação a objetos e das boas práticas de programação. :oops:
Não é bom a quantidade excessiva de if’s, melhor implementar como do primeiro modo, já que o código em cada classe fica mais limpo e as responsabilidades distribuídas de uma melhor forma… :roll:
Obrigado pela dica :smiley:

Criado 30 de agosto de 2012
Ultima resposta 3 de set. de 2012
Respostas 10
Participantes 3