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:

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

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

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

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

  5. 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:

  1. Criar interface com a forma mais abstrata do objeto (no exemplo: “Veículo”)
  2. Criar classes que implementam essa forma mais abstrata (no exemplo: “Carro” e “Caminhão”)
  3. 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() ou new Caminhao().
  4. 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();
    }
}