A diferença fundamental entre o padrão Factory Method e o padrão Abstract Factory reside no nível de abstração e na complexidade dos problemas que eles resolvem.

Factory Method (Factory):

  1. Propósito: O padrão Factory Method foca na criação de um único tipo de objeto.
  2. Implementação: Geralmente implementado por uma única função/método. Este método retorna diferentes tipos de objetos que derivam de uma mesma classe ou interface, dependendo dos argumentos fornecidos.
  3. Uso: É mais adequado quando há uma necessidade de estender a gama de produtos criados (tipos de objetos), mas todos esses produtos compartilham uma interface comum ou uma classe base.
  4. Exemplo: Um método getVeiculo em uma classe VeiculoFactory que pode criar e retornar diferentes tipos de veículos, como carros, bicicletas, caminhões, etc., todos implementando a interface Veiculo.

Abstract Factory:

  1. Propósito: O padrão Abstract Factory é usado para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas.
  2. Implementação: Geralmente consiste em uma interface que cria múltiplos tipos de objetos relacionados. As subclasses concretas dessa interface implementam a criação de todos os tipos de objetos da família.
  3. Uso: Ideal para cenários onde há múltiplos produtos que são relacionados por um tema ou conceito comum e você quer garantir que os objetos criados sejam compatíveis entre si.
  4. Exemplo: Uma FabricaDeMoveis com métodos para criar diferentes tipos de móveis, como criarCadeira, criarSofa, criarMesa. Existem diferentes fábricas, como FabricaDeMoveisVitoriana e FabricaDeMoveisModerna, cada uma criando produtos que combinam entre si (cadeiras, sofás e mesas com estilos vitorianos ou modernos).

Conclusão:

  • Factory Method: Foca na criação de um tipo de objeto e é implementado em um único método.
  • Abstract Factory: Foca na criação de famílias de objetos relacionados e é implementado como um conjunto de métodos para criar diferentes tipos de objetos.

Enquanto o Factory Method é mais simples e lida com a criação de um tipo de objeto por vez, o Abstract Factory é mais complexo e aborda a criação de famílias de objetos que precisam trabalhar juntos ou precisam ser compatíveis.

Implementação

  1. Criar uma interface mais genérica, como “Veículo”
  2. Criar uma interface menos genérica, como “VeículoFactory”, com métodos que retornar subclasses que implementam a interface “Veículo”
  3. Criar Fábricas concretas (TerrestreFactory, AquaticoFactory) que implementam a interface menos genérica “VeiculoFactory”. Na implementação dos métodos da interface, retornar null ou exceção quando a TerrestreFactory tentar criar um veiculo aquático.
  4. Utilizar as fábricas abstratas instanciando a interface menos abstrata e usando o método para criar um objeto Veículo.

Definindo Interfaces para Veículos e Fábrica Abstrata:

public interface Veiculo {
    void tipo();
}
 
public interface VeiculoFactory {
    Carro criarCarro();
    Barco criarBarco();
}
 

Implementando Veículos Concretos:

public class Carro implements Veiculo {
    public void tipo() {
        System.out.println("Carro Terrestre.");
    }
}
 
public class Barco implements Veiculo {
    public void tipo() {
        System.out.println("Barco Aquático.");
    }
}
 

Implementando Fábricas Concretas:

public class TerrestreFactory implements VeiculoFactory {
    public Carro criarCarro() {
        return new Carro();
    }
 
    public Barco criarBarco() {
        // Retornando null ou lançando uma exceção, pois esta fábrica não cria barcos
        return null;
    }
}
 
public class AquaticoFactory implements VeiculoFactory {
    public Carro criarCarro() {
        // Retornando null ou lançando uma exceção, pois esta fábrica não cria carros
        return null;
    }
 
    public Barco criarBarco() {
        return new Barco();
    }
}
 

Utilizando as Fábricas Abstratas:

public class TerrestreFactory implements VeiculoFactory {
    public Carro criarCarro() {
        return new Carro();
    }
 
    public Barco criarBarco() {
        // Retornando null ou lançando uma exceção, pois esta fábrica não cria barcos
        return null;
    }
}
 
public class AquaticoFactory implements VeiculoFactory {
    public Carro criarCarro() {
        // Retornando null ou lançando uma exceção, pois esta fábrica não cria carros
        return null;
    }
 
    public Barco criarBarco() {
        return new Barco();
    }
}