Design de software

Padrão Abstract Factory em Swift: trocando objetos relacionados de uma vez

Abstract Factory agrupa vários objetos compatíveis em famílias de produtos e os substitui de uma vez. Com um exemplo de tema em Swift, este artigo explica como evitar erros de composição e escolher entre Abstract Factory e Factory Method.

4 min de leitura
Imagem de capa de Padrão Abstract Factory em Swift: trocando objetos relacionados de uma vez

Você já trocou toda a interface de um app do tema claro para o escuro?

Quando você troca as cores de botões e rótulos um por um, sempre acaba esquecendo alguma coisa. É fácil o botão ficar com fundo preto enquanto o rótulo continua com fundo branco.

É exatamente aí que o padrão Abstract Factory do Swift se encaixa. Você agrupa os objetos relacionados em um conjunto e troca o conjunto inteiro.

O padrão que altera o ponto de criação de um objeto e o padrão que cria uma família inteira de produtos têm escopos diferentes. Se quiser definir essa fronteira primeiro, confira também Factory Method vs. Abstract Factory.

Neste artigo, vamos resumir o que o padrão Abstract Factory resolve, como trocar objetos relacionados de uma vez com código Swift e quando vale a pena usá-lo ou evitá-lo.


O que é o padrão Abstract Factory?

Em uma frase:

É um padrão que permite trocar, conforme a situação, a fábrica inteira que cria como conjunto objetos que precisam ser compatíveis.

O ponto central são os “objetos que precisam ser usados juntos”. Misturar um botão de tema escuro com um fundo de tema claro seria um problema.

Abstract Factory evita esse tipo de erro de composição.

Ao escolher uma fábrica, suas peças são automaticamente compatíveis. Escolha a fábrica clara e você terá botão, rótulo e fundo claros.

Em vez de escolher as peças individualmente, você escolhe a fábrica inteira.

Essa é toda a ideia do Abstract Factory.


Como trocar objetos relacionados de uma vez no Swift

Com código real, fica muito mais claro. Vamos usar temas de UI como exemplo.

Primeiro, defina os contratos (protocolos) das peças que serão criadas e da fábrica que as produzirá.

protocol Button { func render() -> String }
protocol Label  { func render() -> String }

// A fábrica é responsável pelo conjunto completo de peças compatíveis
protocol ThemeFactory {
    func makeButton() -> Button
    func makeLabel() -> Label
}
Tudo começa definindo um protocol
Tudo começa definindo um protocol

Agora crie uma fábrica para o tema claro e outra para o escuro. Cada fábrica produz apenas peças compatíveis com seu tema.

Escolha uma fábrica e as peças vêm automaticamente como um conjunto
Escolha uma fábrica e as peças vêm automaticamente como um conjunto
struct LightFactory: ThemeFactory {
    func makeButton() -> Button { LightButton() }
    func makeLabel() -> Label  { LightLabel() }
}
struct DarkFactory: ThemeFactory {
    func makeButton() -> Button { DarkButton() }
    func makeLabel() -> Label  { DarkLabel() }
}

O código que desenha a tela só precisa receber uma fábrica. Ele não se importa com qual fábrica é.

func buildScreen(with factory: ThemeFactory) {
    let button = factory.makeButton()
    let label  = factory.makeLabel()
    print(button.render(), label.render())
}

// Trocar o tema exige apenas mudar uma linha da fábrica
buildScreen(with: DarkFactory())

No momento em que você troca LightFactory() por DarkFactory(), o botão e o rótulo passam juntos para o tema escuro.

Você não precisa mais corrigir separadamente as cores do botão e do rótulo.

Do claro ao escuro: uma linha mudou e a tela ficou toda consistente
Do claro ao escuro: uma linha mudou e a tela ficou toda consistente

Qual é a diferença em relação ao Factory Method?

Como os nomes são parecidos e podem confundir, vamos esclarecer a diferença.

Classificação Factory Method Abstract Factory
O que cria Um tipo de objeto Vários tipos de objetos relacionados (um conjunto)
Foco “O que criar?” “Agrupar os que são compatíveis”
Exemplo típico Criar um botão Botão, rótulo e fundo como um conjunto

Em poucas palavras, Factory Method é uma forma de criar uma peça, enquanto Abstract Factory agrupa essas peças em um conjunto.

Também é válido pensar que Abstract Factory usa vários Factory Method internamente.


Quando usar e quando evitar

Depois de usar o padrão, percebi uma divisão clara entre as situações em que ele se encaixa e aquelas em que é exagero.

Quando é uma boa escolha

  • Quando fica claro que a mudança acontece por “conjuntos”, como tema, plataforma ou país
  • Quando é preciso trocar toda uma família de componentes de UI, como entre iOS e macOS
  • Quando meios de pagamento ou drivers de banco de dados são trocados como conjuntos completos

Quando é exagero

  • Quando há apenas um ou dois tipos de objetos para criar
  • Quando as regras de composição mudam com frequência e o conjunto em si é instável

Se existe apenas um objeto e você cria um Abstract Factory, o código aumenta e fica mais difícil de ler.

Use-o quando houver uma razão clara para agrupar os objetos em um conjunto.


Duas perguntas frequentes

P. E se eu precisar adicionar outro tipo de peça depois?

Adicione um método ao protocolo e implemente-o em todas as fábricas. Isso dá trabalho quando há muitas fábricas, então pense nisso antecipadamente se os tipos de peças aumentarem com frequência.

P. Ele também é usado com SwiftUI?

Claro, mas o SwiftUI já oferece formas próprias de injeção, como Environment e @Observable, que costumam ser mais concisas para temas. Abstract Factory se destaca mais com UIKit ou quando uma camada de lógica pura precisa trocar conjuntos completos.


Abstract Factory é, no fim das contas, o padrão que reúne sob uma única alça coisas que não devem funcionar separadamente.

Depois de experimentar uma tela inteira ficar consistente ao mudar o tema em uma única linha, você entende imediatamente por que usar esse padrão. Recomendo começar levando um exemplo pequeno para o código.

Leia também