Ao criar apps com Swift, você escreve código de criação de objetos dezenas de vezes por dia.
Mas, em algum momento, usar apenas init começa a ficar limitante.
É comum começar usando sempre init e procurar o padrão Factory Method conforme o projeto cresce.
Neste artigo, explico o que é o padrão Factory Method em Swift e por que usar uma factory em vez de init, com código real.
Padrão Factory Method em uma frase
Vamos começar pela resposta principal.
O Factory Method extrai a lógica de criação para um método separado fora de init, permite nomeá-lo e oferece liberdade para escolher o tipo retornado.
Em Swift, geralmente estamos falando de um método factory estático criado com static func.
Aqui tratamos da factory estática, que encapsula a criação em um método de tipo. Ela difere do padrão GoF, em que a subclasse decide o tipo criado; comparei essa distinção em Diferença entre Factory Method e Abstract Factory.
init só funciona dentro das regras definidas pela linguagem.
Não é possível dar outro nome a ele, e sempre é preciso criar uma nova instância do próprio tipo.
Os métodos factory removem essas limitações.
Veja um exemplo simples.
struct Color {
let r, g, b: Double
// Expresse a intenção de criação no nome
static func rgb(_ r: Double, _ g: Double, _ b: Double) -> Color {
Color(r: r, g: g, b: b)
}
static func gray(_ v: Double) -> Color {
Color(r: v, g: v, b: v)
}
}
Ao chamar como Color.gray(0.5), fica claro, só pelo código, que isso cria a cor cinza.
Por que usar uma factory em vez de init?
Com base na minha experiência, cheguei a quatro motivos principais.
Primeiro, você pode dar um nome.
Como todos os init têm o mesmo nome, a distinção depende apenas dos parâmetros.
Se houver vários inicializadores que recebem dois Double iguais, é fácil se confundir.
Os métodos factory expressam a intenção no nome, como from(hex:) e rgb(_:_:_:).
Segundo, não é preciso criar uma nova instância toda vez.
init sempre retorna um novo objeto, mas uma factory pode devolver um valor em cache ou um singleton.
Terceiro, o tipo retornado pode ser escolhido com flexibilidade.
Dependendo da situação, é possível retornar um subtipo ou outra implementação.
Quarto, o tratamento de falhas pode ser expresso com mais clareza.
Abaixo, um exemplo de factory usando cache.
final class IconCache {
private static var store: [String: Icon] = [:]
// Reutiliza o ícone já criado quando o nome é igual
static func icon(named name: String) -> Icon {
if let cached = store[name] { return cached }
let icon = Icon(name: name)
store[name] = icon
return icon
}
}
Ao solicitar o mesmo ícone várias vezes, você economiza memória.
Então não precisamos mais usar init?
Não, de jeito nenhum.
A factory não substitui init; ela é uma ferramenta para encapsulá-lo.
Mesmo dentro do método factory, no fim das contas você chama init para criar o objeto.
Para tipos por valor simples ou lógica de criação óbvia, init é melhor.
Encapsular tudo em uma factory sem necessidade só aumenta o código e dificulta a leitura.
A factory brilha em situações específicas:
- Quando há várias formas de criação e você quer diferenciá-las pelos nomes
- Quando é necessário reutilizar, com cache ou pooling
- Quando você quer esconder um processo complexo de inicialização em um único lugar
- Quando quer ocultar a implementação retornando um tipo de protocolo
Se nenhuma dessas condições se aplicar, usar init é a escolha certa.
A biblioteca padrão do Swift também faz essa distinção.
Array(repeating:count:) é um init, mas propriedades estáticas como UIColor.systemBlue são, na prática, primas das factories.
Critérios práticos para decidir
Organizei em uma tabela os critérios que uso quando fico em dúvida.
| Situação | Recomendação |
|---|---|
| Armazenar valores simples | init |
| Há várias formas de criação | Método factory |
| Reutilização ou cache de instâncias | Método factory |
| Ocultar a implementação e retornar um protocolo | Método factory |
| Inicialização termina em uma linha | init |
Em resumo, init cuida de “como criar”, enquanto a factory cuida de “o que e por que criar”.
Eles não competem; são parceiros com papéis diferentes.
Recomendo começar com init e migrar para uma factory quando a lógica de criação ficar complexa.
Basta lembrar os critérios de hoje para deixar o código mais limpo. Boa programação em Swift!

