Padrão Factory
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy. Lição 66 de 87.
O Factory Pattern é um padrão de projeto criacional que delega a criação de objetos a um método ou classe separado. Em vez de usar new diretamente no seu código, você solicita a uma fábrica que crie objetos para você. Isso é especialmente útil quando você tem várias classes relacionadas que compartilham uma interface ou classe-pai comum.
Considere um sistema de notificações que pode enviar e-mails, SMS ou notificações push. Sem uma fábrica, seu código precisaria conhecer cada classe concreta:
// Sem Factory - o cliente deve conhecer todas as classes concretas
Notification notification;
if (type.equals("email")) {
notification = new EmailNotification();
} else if (type.equals("sms")) {
notification = new SMSNotification();
}Com o Padrão Factory, você centraliza esta lógica de criação:
public interface Notification {
void send(String message);
}
public class EmailNotification implements Notification {
public void send(String message) {
System.out.println("Email: " + message);
}
}
public class SMSNotification implements Notification {
public void send(String message) {
System.out.println("SMS: " + message);
}
}
public class NotificationFactory {
public static Notification create(String type) {
if (type.equals("email")) {
return new EmailNotification();
} else if (type.equals("sms")) {
return new SMSNotification();
}
return null;
}
}Agora o código do cliente está mais limpo e não depende de classes concretas:
Notification notification = NotificationFactory.create("email");
notification.send("Hello!"); // Saída: Email: Hello!O principal benefício é que adicionar novos tipos de notificação exige apenas atualizar a fábrica: o código do cliente permanece inalterado. Isso segue o princípio de programar para uma interface, tornando seu sistema mais flexível e fácil de estender.
Desafio
FácilVamos criar um sistema de desenho de formas usando o Factory Pattern! Em vez de criar objetos de formas diretamente em todo o seu código, você centralizará a lógica de criação em uma fábrica que produz diferentes tipos de formas com base em um identificador de string simples.
Você organizará seu código em quatro arquivos:
Shape.java: Defina uma interface chamadaShapeque sirva como contrato comum para todas as formas. Sua interface deve declarar um único métododraw()que não retorna nada, mas imprime informações sobre a forma que está sendo desenhada.Shapes.java: Crie três classes que implementem sua interfaceShape:Circle— seu métododraw()deve imprimirDrawing a CircleRectangle— seu métododraw()deve imprimirDrawing a RectangleTriangle— seu métododraw()deve imprimirDrawing a TriangleShapeFactory.java: Crie a classe fábrica que gerencia a criação de formas. SuaShapeFactorydeve ter um método estáticocreateShape(String type)que retorne umaShape. Com base no parâmetro type:- Se type for igual a
"circle", retorne uma novaCircle - Se type for igual a
"rectangle", retorne uma novaRectangle - Se type for igual a
"triangle", retorne uma novaTriangle - Para qualquer outro valor, retorne
null
- Se type for igual a
Main.java: Reúna seu sistema de fábrica! Você receberá duas entradas: dois tipos de forma (ambos Strings).Para cada entrada, use sua
ShapeFactorypara criar a forma e armazene-a em uma variávelShape. Se a fábrica retornar uma forma válida (não nula), chame seu métododraw(). Se retornar null, imprimaUnknown shape: [type], em que [type] é a entrada fornecida.Processe as duas entradas na ordem, cada uma em sua própria linha de saída.
Você receberá duas entradas na ordem: o primeiro tipo de forma (String) e o segundo tipo de forma (String).
Observe como sua classe Main nunca usa new Circle() ou new Rectangle() diretamente. Ela conhece apenas a interface Shape e pede à fábrica que crie os objetos. Esse é o poder do Factory Pattern: o código cliente fica desacoplado das classes concretas!
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lê dois tipos de forma
String type1 = scanner.nextLine();
String type2 = scanner.nextLine();
// TODO: Use ShapeFactory para criar a primeira forma
// Se a forma não for null, chame draw()
// If the shape is null, print "Unknown shape: [type]"
// TODO: Faça o mesmo para a segunda forma
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão IteratorPratique por conta própria: Compilador de Java online