Menu
Coddy logo textTech

Padrão Factory

Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy — lição 53 de 70.

O padrão Factory é um padrão de criação 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 factory crie objetos para você. Isso centraliza a lógica de criação e torna seu código mais flexível.

Considere um cenário onde você precisa criar diferentes tipos de documentos. Sem uma factory, seu código se torna fortemente acoplado a classes específicas:

// Sem Factory - lógica de criação dispersa
IDocument doc;
if (type == "pdf")
    doc = new PdfDocument();
else if (type == "word")
    doc = new WordDocument();

Uma fábrica encapsula essa tomada de decisão em um só lugar:

public interface IDocument
{
    void Open();
}

public class PdfDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening PDF");
}

public class WordDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening Word");
}

public class DocumentFactory
{
    public IDocument Create(string type)
    {
        return type switch
        {
            "pdf" => new PdfDocument(),
            "word" => new WordDocument(),
            _ => throw new ArgumentException("Unknown type")
        };
    }
}

Agora, o código cliente simplesmente solicita o que precisa sem conhecer as classes concretas:

var factory = new DocumentFactory();
IDocument doc = factory.Create("pdf");
doc.Open();  // Abrindo PDF

O padrão Factory brilha quando você precisa adicionar novos tipos mais tarde. Adicionar um SpreadsheetDocument requer mudanças apenas na factory, não em todos os lugares onde os documentos são criados. Esta separação torna sua base de código mais fácil de manter e testar.

challenge icon

Desafio

Fácil

Vamos construir um sistema de notificação usando o padrão Factory. Em vez de criar diferentes tipos de notificação diretamente em todo o seu código, você centralizará a lógica de criação em uma classe factory que decide qual notificação criar com base em um simples identificador de string.

Você organizará seu código em três arquivos:

  • Notification.cs: Defina uma interface INotification no namespace Notifications com um único método Send(string message) que retorna uma string. Em seguida, crie três classes que implementam esta interface:
    • EmailNotification - retorna "Email: {message}"
    • SmsNotification - retorna "SMS: {message}"
    • PushNotification - retorna "Push: {message}"
  • NotificationFactory.cs: Crie uma classe NotificationFactory no mesmo namespace com um método Create(string type) que retorna a INotification apropriada com base na string de tipo:
    • "email" retorna uma EmailNotification
    • "sms" retorna uma SmsNotification
    • "push" retorna uma PushNotification
    Para qualquer tipo não reconhecido, retorne uma EmailNotification como padrão.
  • Program.cs: Reúna tudo criando uma instância da factory e usando-a para criar notificações com base na entrada. A factory lida com toda a tomada de decisão sobre qual classe concreta instanciar.

Você receberá duas entradas:

  • O tipo de notificação (ex: sms)
  • A mensagem a ser enviada (ex: Your order has shipped)

Use sua factory para criar o tipo de notificação apropriado, chame seu método Send com a mensagem e imprima o resultado.

Por exemplo, se as entradas forem push e Meeting in 5 minutes, a saída deve ser:

Push: Meeting in 5 minutes

Observe como seu código principal nunca usa new EmailNotification() ou similar - ele simplesmente pede à factory o que precisa. Se você adicionar posteriormente uma SlackNotification, precisará apenas atualizar a factory, não todos os lugares que criam notificações!

Folha de consulta

O padrão Factory é um padrão de criação que delega a criação de objetos para um método ou classe separada, centralizando a lógica de criação e tornando o código mais flexível.

Sem uma factory, a criação de objetos fica espalhada e fortemente acoplada:

// Sem Factory - lógica de criação espalhada
IDocument doc;
if (type == "pdf")
    doc = new PdfDocument();
else if (type == "word")
    doc = new WordDocument();

Com uma factory, a lógica de criação é encapsulada em um só lugar:

public interface IDocument
{
    void Open();
}

public class PdfDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening PDF");
}

public class WordDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening Word");
}

public class DocumentFactory
{
    public IDocument Create(string type)
    {
        return type switch
        {
            "pdf" => new PdfDocument(),
            "word" => new WordDocument(),
            _ => throw new ArgumentException("Unknown type")
        };
    }
}

O código do cliente solicita objetos sem conhecer as classes concretas:

var factory = new DocumentFactory();
IDocument doc = factory.Create("pdf");
doc.Open();  // Opening PDF

O padrão Factory facilita a adição de novos tipos - as mudanças são isoladas na factory, não espalhadas por toda a base de código.

Experimente você mesmo

using System;
using Notifications;

class Program
{
    public static void Main(string[] args)
    {
        // Ler a entrada
        string type = Console.ReadLine();
        string message = Console.ReadLine();

        // TODO: Criar uma instância de NotificationFactory

        // TODO: Usar a fábrica para criar a notificação apropriada

        // TODO: Chamar o método Send e imprimir o resultado
    }
}
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