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):
- Propósito: O padrão Factory Method foca na criação de um único tipo de objeto.
- 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.
- 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.
- Exemplo: Um método
getVeiculoem uma classeVeiculoFactoryque pode criar e retornar diferentes tipos de veículos, como carros, bicicletas, caminhões, etc., todos implementando a interfaceVeiculo.
Abstract Factory:
- Propósito: O padrão Abstract Factory é usado para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas.
- 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.
- 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.
- Exemplo: Uma
FabricaDeMoveiscom métodos para criar diferentes tipos de móveis, comocriarCadeira,criarSofa,criarMesa. Existem diferentes fábricas, comoFabricaDeMoveisVitorianaeFabricaDeMoveisModerna, 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
- Criar uma interface mais genérica, como “Veículo”
- Criar uma interface menos genérica, como “VeículoFactory”, com métodos que retornar subclasses que implementam a interface “Veículo”
- 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.
- 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();
}
}