Menu
Coddy logo textTech

Padrão Factory

Parte da seção Programação Orientada a Objetos do Journey de PHP da Coddy — lição 72 de 91.

O Padrão Factory é um padrão de projeto criacional que delega a criação de objetos para uma classe ou método separado. Em vez de usar new diretamente em todo o seu código, você solicita que uma fábrica crie objetos para você.

Este padrão é particularmente útil quando você tem várias classes relacionadas que compartilham uma interface comum e deseja decidir qual delas instanciar com base em alguma condição. Considere um sistema de notificação que pode enviar mensagens através de diferentes canais:

<?php
interface Notification {
    public function send(string $message): string;
}

class EmailNotification implements Notification {
    public function send(string $message): string {
        return "Email: $message";
    }
}

class SmsNotification implements Notification {
    public function send(string $message): string {
        return "SMS: $message";
    }
}

Sem uma fábrica, você espalharia instruções if e chamadas new por toda parte. A fábrica centraliza essa lógica:

<?php
class NotificationFactory {
    public static function create(string $type): Notification {
        return match($type) {
            'email' => new EmailNotification(),
            'sms' => new SmsNotification(),
            default => throw new InvalidArgumentException("Unknown type: $type")
        };
    }
}

$notification = NotificationFactory::create('email');
echo $notification->send('Hello!');

Saída:

Email: Hello!

O principal benefício é que seu código depende da interface Notification, não de classes concretas. Se você adicionar posteriormente uma classe PushNotification, você apenas atualiza a fábrica. Todo o código que utiliza a fábrica ganha automaticamente acesso ao novo tipo sem modificação.

challenge icon

Desafio

Fácil

Vamos construir um sistema gerador de documentos usando o Factory Pattern. Diferentes tipos de documentos (PDF, HTML, Texto Simples) compartilham uma interface comum, mas produzem saídas diferentes — um cenário perfeito para centralizar a criação de objetos em uma fábrica.

Você organizará seu código em quatro arquivos:

  • Document.php — Crie uma interface Document que define o contrato que todos os tipos de documentos devem seguir. Ela deve ter um único método render(string $content): string que recebe o conteúdo e retorna a saída do documento formatada.
  • Documents.php — Inclua a interface Document e crie três classes que a implementam:
    • PdfDocument — Seu método render() retorna "PDF: $content"
    • HtmlDocument — Seu método render() retorna "<html>$content</html>"
    • TextDocument — Seu método render() retorna "TXT: $content"
  • DocumentFactory.php — Inclua o arquivo Documents e crie uma classe DocumentFactory com um método estático create(string $type): Document. Este método deve usar match para retornar o objeto de documento apropriado com base no tipo:
    • "pdf" retorna um novo PdfDocument
    • "html" retorna um novo HtmlDocument
    • "text" retorna um novo TextDocument
    • Qualquer outro tipo deve lançar uma InvalidArgumentException com a mensagem "Unknown document type: $type"
  • main.php — Inclua o arquivo DocumentFactory. Você receberá duas entradas: um tipo de documento e o conteúdo para renderizar.

    Use a fábrica para criar o tipo de documento apropriado, depois chame seu método render() com o conteúdo e imprima o resultado.

    Em uma nova linha, imprima "Factory benefit: Adding new types only requires updating the factory" para destacar por que este padrão é valioso.

O Factory Pattern mantém seu código flexível — quando você precisar adicionar um MarkdownDocument mais tarde, você apenas atualizará a fábrica enquanto todo o código existente continua funcionando sem alterações.

Folha de consulta

O Factory Pattern (Padrão de Fábrica) delega a criação de objetos para uma classe ou método separado, em vez de usar new diretamente em todo o seu código.

Este padrão é útil quando você tem várias classes relacionadas que compartilham uma interface comum e precisa decidir qual delas instanciar com base em uma condição.

Exemplo com um sistema de notificação:

<?php
interface Notification {
    public function send(string $message): string;
}

class EmailNotification implements Notification {
    public function send(string $message): string {
        return "Email: $message";
    }
}

class SmsNotification implements Notification {
    public function send(string $message): string {
        return "SMS: $message";
    }
}

A fábrica centraliza a lógica de criação de objetos:

<?php
class NotificationFactory {
    public static function create(string $type): Notification {
        return match($type) {
            'email' => new EmailNotification(),
            'sms' => new SmsNotification(),
            default => throw new InvalidArgumentException("Unknown type: $type")
        };
    }
}

$notification = NotificationFactory::create('email');
echo $notification->send('Hello!'); // Output: Email: Hello!

Principais benefícios:

  • O código depende da interface, não de classes concretas
  • Adicionar novos tipos requer apenas a atualização da fábrica
  • O código existente ganha acesso automaticamente a novos tipos sem modificação

Experimente você mesmo

<?php
require_once 'DocumentFactory.php';

// Ler a entrada
$type = trim(fgets(STDIN));
$content = trim(fgets(STDIN));

// TODO: Use DocumentFactory para criar o tipo de documento apropriado
// TODO: Chame o método render() com o conteúdo e imprima o resultado
// TODO: Em uma nova linha, imprima "Factory benefit: Adding new types only requires updating the factory"

?>
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