Evento Presencial: Imersão Avançada em Inteligência Artificial

Saiba mais

Abstract Factory: como criar famílias sem misturar objetos incompatíveis?

Rodrigo Branas
Rodrigo Branas
05 mai 2026·3 min de leitura
#design-patterns#abstract-factory-pattern-typescript

Uma factory cria objetos. Uma Abstract Factory cria objetos que precisam fazer sentido juntos.

Essa diferença parece pequena até uma aplicação permitir combinações inválidas: uma política de cobrança anual com calendário mensal, um botão de um tema com a janela de outro ou um tipo de empréstimo com o cálculo de parcelas errado.

O problema não é esconder o new. É preservar a coerência de uma família.

O problema aparece na combinação

Considere uma assinatura com duas modalidades:

  • mensal, cobrada a cada mês;
  • anual, cobrada uma vez e renovada depois de doze meses.

Podemos espalhar condições:

if (plan === "monthly") {
  billing = new MonthlyBilling();
  schedule = new MonthlySchedule();
}

if (plan === "annual") {
  billing = new AnnualBilling();
  schedule = new AnnualSchedule();
}

Enquanto a criação vive em um único lugar, isso pode ser suficiente. O risco começa quando vários clientes precisam conhecer as combinações ou quando alguém instancia AnnualBilling com MonthlySchedule.

Cada classe isolada é válida. A família é que ficou incoerente.

A família como abstração

Uma Abstract Factory declara os produtos relacionados:

interface SubscriptionFactory {
  createBilling(): BillingPolicy;
  createSchedule(): RenewalSchedule;
}

Cada implementação preserva uma combinação:

class MonthlySubscriptionFactory implements SubscriptionFactory {
  createBilling() {
    return new MonthlyBilling();
  }

  createSchedule() {
    return new MonthlySchedule();
  }
}

class AnnualSubscriptionFactory implements SubscriptionFactory {
  createBilling() {
    return new AnnualBilling();
  }

  createSchedule() {
    return new AnnualSchedule();
  }
}

O caso de uso recebe uma família, não um tipo e vários if:

class CreateSubscription {
  constructor(readonly factory: SubscriptionFactory) {}

  execute() {
    const billing = this.factory.createBilling();
    const schedule = this.factory.createSchedule();
    return new Subscription(billing, schedule);
  }
}

O Composition Root escolhe a factory concreta. O núcleo trabalha apenas com os contratos.

Qual eixo ficou fácil de estender?

Adicionar uma nova família, como QuarterlySubscriptionFactory, é simples: implementamos todos os produtos relacionados.

Adicionar um novo tipo de produto é mais caro. Se a interface ganhar createNotificationPolicy(), todas as factories precisam ser alteradas.

Abstract Factory favorece um cenário em que:

  • as famílias variam;
  • o conjunto de produtos é relativamente estável;
  • misturar produtos de famílias diferentes cria um problema real.

O pattern não elimina mudanças. Ele escolhe qual direção de mudança será melhor suportada.

Abstract Factory não exige Singleton

É comum encontrar factories que devolvem sempre as mesmas instâncias ou acessam repositories globais. Essa é outra decisão.

Abstract Factory administra famílias. Singleton administra a existência de uma única instância e normalmente oferece acesso global a ela.

Podemos combinar os dois, mas um não implica o outro. A factory pode criar objetos novos, devolver objetos injetados ou controlar outro ciclo de vida sem se tornar global.

Separar as intenções melhora os testes. Em um cenário podemos fornecer uma família de produção; em outro, uma família de Fakes independentes.

E o Factory Method?

Factory Method permite que uma subclasse varie um produto utilizado por um algoritmo. Abstract Factory oferece um objeto responsável por produzir vários tipos relacionados.

Os métodos de uma Abstract Factory podem internamente ser Factory Methods, mas os patterns resolvem problemas diferentes. O artigo sobre Factory Method ou Abstract Factory compara diretamente as duas estruturas.

Quando não usar?

Não crie uma família abstrata quando:

  • existe apenas uma combinação;
  • os produtos não possuem relação de compatibilidade;
  • injetar os dois objetos diretamente é mais claro;
  • uma função pequena concentra toda a seleção;
  • o conjunto de produtos muda mais que as famílias.

Uma interface com cinco métodos e uma única implementação pode apenas esconder construções simples atrás de indireção.

Checklist de decisão

Antes de criar a factory, escreva as combinações válidas em uma tabela. Verifique se os produtos realmente mudam como família, se um cliente poderia misturá-los por engano e se adicionar uma família é mais provável que adicionar um produto. Depois compare com duas alternativas: injetar os objetos prontos ou concentrar uma condição em uma função. Se a tabela não contém incompatibilidade real, provavelmente não existe uma força suficiente para Abstract Factory.

Conclusão

Abstract Factory não serve apenas para organizar construtores. Ele representa uma decisão de compatibilidade entre objetos que nascem em conjunto.

Use quando diferentes famílias precisam permanecer coerentes e o cliente não deveria conhecer suas classes concretas. Se a decisão é apenas escolher uma implementação isolada, uma factory function ou injeção direta pode ser suficiente.

Saiba mais

Formação em Arquitetura de Software

Aprenda tudo sobre Clean Code, Refactoring, OO, Test-Driven Development, Hexagonal, Clean Architecture, Domain-Driven Design, Microservices, Event-Driven Architecture, CQRS, SOLID e Design Patterns.

Cookies e privacidade

Utilizamos cookies para melhorar sua experiência, analisar o tráfego do site e personalizar conteúdo. Você pode aceitar todos, rejeitar ou personalizar suas preferências.