Ao estudar padrões de projeto, há um ponto em que quase todo mundo acaba travando.
São os padrões Strategy e State.
Quando colocamos os diagramas UML (Unified Modeling Language, linguagem de modelagem unificada) lado a lado, eles parecem praticamente copiados e colados. Há uma interface, várias implementações e um contexto que as mantém.
É natural pensar: “Isso não é só um nome diferente?”
Vamos começar pela conclusão. O que separa os dois padrões não é a estrutura, mas a intenção. Strategy troca o algoritmo de fora; State faz o próprio estado avançar internamente para o próximo estado.
Tenha essa frase em mente ao continuar lendo e você não vai mais confundi-los.
A implementação que remove condicionais reais usando objetos de estado continua passo a passo em Refatorando o padrão State em Swift.
Por que as estruturas são tão iguais?
Ambos são padrões comportamentais do livro de padrões de projeto do GoF (Gang of Four).
Ambos usam os mesmos elementos: uma interface comum, várias classes que a implementam e um contexto que as mantém.
Por isso, olhando apenas para o código, é realmente difícil diferenciá-los.
Em código, o padrão Strategy fica assim.
protocol PaymentStrategy {
func pay(_ amount: Int)
}
struct CardPayment: PaymentStrategy {
func pay(_ amount: Int) { print("Pagamento de \(amount) won no cartão") }
}
struct KakaoPay: PaymentStrategy {
func pay(_ amount: Int) { print("Pagamento de \(amount) won com Kakao Pay") }
}
final class Checkout {
var strategy: PaymentStrategy
init(strategy: PaymentStrategy) { self.strategy = strategy }
func pay(_ amount: Int) { strategy.pay(amount) }
}
let checkout = Checkout(strategy: CardPayment())
checkout.pay(10000)
checkout.strategy = KakaoPay() // Trocado externamente
checkout.pay(5000)
// Saída:
// Pagamento de 10000 won no cartão
// Pagamento de 5000 won com Kakao Pay
O ponto importante aqui é quem troca a strategy: o código do cliente externo.
Quem mudou o meio de pagamento de cartão para Kakao Pay foi o desenvolvedor, ou seja, alguém de fora.
A própria Strategy não faz ideia do que vem depois. E não se importa.
Então, o que muda no padrão State?
No padrão State, os próprios estados decidem as transições.
Pense em um semáforo. O sinal vermelho sabe que o próximo é o verde, e o verde sabe que o próximo é o amarelo.
Em outras palavras, a regra para avançar ao próximo estado fica dentro de cada estado.
protocol TrafficState {
func next(_ light: TrafficLight)
}
final class Red: TrafficState {
func next(_ light: TrafficLight) {
print("Vermelho → verde")
light.state = Green() // O estado define sozinho o próximo
}
}
final class Green: TrafficState {
func next(_ light: TrafficLight) {
print("Verde → amarelo")
light.state = Yellow()
}
}
final class Yellow: TrafficState {
func next(_ light: TrafficLight) {
print("Amarelo → vermelho")
light.state = Red()
}
}
final class TrafficLight {
var state: TrafficState = Red()
func change() { state.next(self) }
}
let light = TrafficLight()
light.change()
light.change()
light.change()
// Saída:
// Vermelho → verde
// Verde → amarelo
// Amarelo → vermelho
Está vendo a diferença?
No Strategy, fizemos a troca diretamente de fora, como em checkout.strategy = KakaoPay().
No State, light.state = Green() é feito pela própria classe de estado. O cliente apenas chama change().
Esse é exatamente o ponto central.
Strategy é trocado de fora; State avança sozinho por dentro.
A diferença decisiva em três pontos
Explicar apenas com palavras pode gerar confusão de novo, então vamos resumir em uma tabela.
| Categoria | Padrão Strategy | Padrão State |
|---|---|---|
| Intenção | Substituir o algoritmo | Mudar o comportamento conforme o estado |
| Quem faz a transição | Cliente externo | O próprio objeto de estado |
| Relação entre objetos | Não se conhecem (independentes) | Conhecem e referenciam uns aos outros |
| Ciclo de vida | Normalmente permanece após ser escolhido | Muda continuamente durante a execução |
Preste atenção especialmente à segunda e à terceira linha.
As strategies não conhecem a existência umas das outras. Um pagamento com cartão não precisa conhecer o Kakao Pay.
Já os estados precisam se conhecer. O sinal vermelho cria diretamente o objeto do sinal verde e o entrega a ele.
Esse “conhecer ou não conhecer uns aos outros” é a pista mais confiável para distinguir os dois padrões no código.
Quando usar e quando evitar?
Estes são os critérios que uso para decidir isso no trabalho.
| Situação | Decisão |
|---|---|
| Quando existem apenas várias formas de fazer a mesma coisa (ordenação, pagamento, compressão) | Padrão Strategy |
| Quando o objeto age de forma diferente conforme a situação, e a situação muda | Padrão State |
| Quando as regras de transição viram um bloco complexo de if-else | Resolver com o padrão State |
| Quando é simples o bastante para passar apenas uma função | Ambos são exagero; use uma closure |
Também há um ponto importante.
Se houver apenas 2 ou 3 estados e as transições forem simples, muitas vezes enum e switch já são suficientes, sem introduzir um padrão.
Padrões são ferramentas para controlar a complexidade, não enfeites para formalizar código simples.
Em entrevistas, a pergunta costuma ser assim
P. Os padrões Strategy e State têm a mesma estrutura. Como diferenciá-los?
A estrutura é quase igual, mas a intenção é diferente. Strategy serve para substituir um algoritmo externamente, enquanto State serve para mudar o comportamento conforme o estado interno. A diferença decisiva é quem faz a transição: o cliente no Strategy e o próprio objeto de estado no State.
P. No padrão State, os estados referenciam uns aos outros. Isso não é um problema?
De fato, surge acoplamento entre os estados. Para reduzi-lo, você pode tirar a lógica de transição dos estados e colocá-la no contexto ou em uma tabela de transição separada. Quando os estados aumentam e as transições ficam entrelaçadas, usar uma biblioteca de máquinas de estado também é uma opção.
Mesmo que os diagramas pareçam idênticos, não se assuste. Basta perguntar “quem faz a transição?” e a resposta aparece imediatamente.
Se a troca acontece de fora, é Strategy; se o estado avança sozinho por dentro, é State. Guardando essa frase, o artigo de hoje já cumpriu seu papel. Voltarei com outro padrão fácil de confundir.

