Menu
Coddy logo textTech

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 para um método ou classe separada. Em vez de usar new diretamente no seu código, você solicita que uma fábrica crie objetos para você. Isso é especialmente útil quando você tem várias classes relacionadas que compartilham uma interface ou pai comum.

Considere um sistema de notificação que pode enviar e-mails, SMS ou notificações push. Sem uma factory, 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 Factory Pattern, 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 a adição de novos tipos de notificação exige apenas a atualização da factory — 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.

challenge icon

Desafio

Fácil

Vamos construir um sistema de desenho de formas usando o Factory Pattern! Em vez de criar objetos de forma 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 chamada Shape que sirva como o contrato comum para todas as formas. Sua interface deve declarar um único método draw() 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 interface Shape:

    Circle - seu método draw() deve imprimir Drawing a Circle

    Rectangle - seu método draw() deve imprimir Drawing a Rectangle

    Triangle - seu método draw() deve imprimir Drawing a Triangle

  • ShapeFactory.java: Crie a classe de fábrica que lida com a criação de formas. Sua ShapeFactory deve ter um método estático createShape(String type) que retorna um Shape. Com base no parâmetro type:
    • Se type for igual a "circle", retorne um novo Circle
    • Se type for igual a "rectangle", retorne um novo Rectangle
    • Se type for igual a "triangle", retorne um novo Triangle
    • Para qualquer outro valor, retorne null
  • Main.java: Reúna seu sistema de fábrica! Você receberá duas entradas: dois tipos de formas (ambas Strings).

    Para cada entrada, use sua ShapeFactory para criar a forma e armazená-la em uma variável Shape. Se a fábrica retornar uma forma válida (não nula), chame seu método draw(). Se retornar nulo, imprima Unknown shape: [type] onde [type] é a entrada que foi fornecida.

    Processe ambas as entradas em ordem, cada uma em sua própria linha de saída.

Você receberá duas entradas em 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 solicita à fábrica a criação dos objetos. Este é o poder do Factory Pattern: o código do cliente é desacoplado das classes concretas!

Folha de consulta

O Factory Pattern (Padrão de Fábrica) é um padrão de projeto criacional que delega a criação de objetos para um método ou classe separada, centralizando a lógica de criação e desacoplando o código do cliente das implementações concretas.

Em vez de instanciar objetos diretamente com new, você usa um método de fábrica:

// Sem Factory - o cliente depende de classes concretas
Notification notification;
if (type.equals("email")) {
    notification = new EmailNotification();
} else if (type.equals("sms")) {
    notification = new SMSNotification();
}

Com o Factory Pattern, defina uma interface comum e implementações concretas:

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);
    }
}

Crie uma classe de fábrica com um método de criação estático:

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;
    }
}

O código do cliente usa a fábrica em vez da instanciação direta:

Notification notification = NotificationFactory.create("email");
notification.send("Hello!");  // Saída: Email: Hello!

Benefícios: Adicionar novos tipos requer apenas a atualização da fábrica — o código do cliente permanece inalterado. Isso segue o princípio de programar para uma interface, tornando os sistemas mais flexíveis e fáceis de estender.

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 formas
        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()
        // Se a forma for null, imprima "Unknown shape: [type]"
        
        // TODO: Faça o mesmo para a segunda forma
        
    }
}
quiz iconTeste seus conhecimentos

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