O padrão Factory, especificamente o Factory Method, tem como objetivo principal simplificar a criação de objetos.
Ele resolve principalmente o problema de criar instâncias de classes sem especificar a classe exata do objeto que será criado. Isso é alcançado através da definição de uma interface para criar um objeto, mas deixando que subclasses decidam qual classe instanciar. Os problemas específicos que o padrão Factory Method busca resolver incluem:
-
Acoplamento entre Criação e Implementação: Em muitas situações, é desejável reduzir o acoplamento entre o código que cria um objeto e a implementação concreta desse objeto. O Factory Method permite isso ao delegar a responsabilidade de criação de objetos para subclasses.
-
Extensibilidade e Flexibilidade: O padrão Factory Method torna o código mais flexível e extensível. Ele permite introduzir novas classes concretas sem alterar o código que as utiliza, seguindo o princípio aberto/fechado.
-
Substituição de Construtores Diretos: O uso direto de construtores para criar objetos pode levar a dependências rígidas e acoplamento. O Factory Method oferece uma alternativa que encapsula e abstrai o processo de criação.
-
Decisões Dinâmicas na Criação de Objetos: O padrão permite que as decisões sobre quais classes instanciar possam ser tomadas em tempo de execução, com base em lógica condicional, configurações ou outros critérios.
-
Isolamento de Complexidades de Criação: Se a criação de um objeto for complexa ou envolver lógica de configuração especial, o Factory Method pode isolar essa complexidade em um único local.
Em resumo, o padrão Factory Method é uma solução eficaz para desacoplar a criação de objetos de sua utilização, permitindo maior flexibilidade e manutenção mais fácil do código. Ele é particularmente útil em frameworks e bibliotecas, onde o código precisa ser genérico e capaz de trabalhar com subclasses fornecidas pelos usuários do framework ou biblioteca.
Exemplo de implementação
Passos:
- Criar interface com a forma mais abstrata do objeto (no exemplo: “Veículo”)
- Criar classes que implementam essa forma mais abstrata (no exemplo: “Carro” e “Caminhão”)
- Criar uma classe com a Factory e um método que recebe um parâmetro que define qual o tipo de classe vai ser criada. A lógica pode ser feita com ifs ou switch, retornando
new Carro()ounew Caminhao(). - Utilizando a Factory: Instancia a interface e chama o método factory passando o parâmetro que determina o tipo de subclasse a ser criado.
Definindo a Interface Veículo e as Classes Concretas:
public interface Veiculo {
void tipo();
}
public class Carro implements Veiculo {
public void tipo() {
System.out.println("Um carro foi criado.");
}
}
public class Caminhao implements Veiculo {
public void tipo() {
System.out.println("Um caminhão foi criado.");
}
}
Implementando a Factory
public class VeiculoFactory {
// Método factory
public static Veiculo getVeiculo(String tipoVeiculo) {
if (tipoVeiculo == null) {
return null;
}
if (tipoVeiculo.equalsIgnoreCase("CARRO")) {
return new Carro();
} else if (tipoVeiculo.equalsIgnoreCase("CAMINHAO")) {
return new Caminhao();
}
return null;
}
}
Utilizando a Factory:
public class Main {
public static void main(String[] args) {
Veiculo veiculo1 = VeiculoFactory.getVeiculo("CARRO");
veiculo1.tipo();
Veiculo veiculo2 = VeiculoFactory.getVeiculo("CAMINHAO");
veiculo2.tipo();
}
}