Bora falar do padrão Strategy?

Published: (February 10, 2026 at 05:04 PM EST)
4 min read
Source: Dev.to

Source: Dev.to

Se você já se pegou pensando “putz, esse if/else aqui tá crescendo demais” ou “cada nova regra quebra algo que já funcionava”, é bem provável que o padrão Strategy seja exatamente o que você está procurando.

Neste post, vamos falar:

  • O que é o Strategy
  • Qual problema ele resolve
  • Quando usar (e quando NÃO usar)
  • Exemplos práticos

O problema clássico

Imagine um sistema que precisa executar uma ação de formas diferentes dependendo do contexto:

  • Tipos diferentes de cálculo
  • Regras que mudam por ambiente (QA, prod)
  • Variações de comportamento por cliente, país ou feature

O caminho mais comum (e perigoso) costuma ser algo assim:

if tipo == A {
    // faz isso
} else if tipo == B {
    // faz aquilo
} else if tipo == C {
    // faz outra coisa
}

Funciona? Funciona.
Escala? Nem um pouco 😅

Cada nova regra:

  • aumenta a complexidade
  • quebra o princípio aberto/fechado (Open/Closed)
  • transforma a função num monstro difícil de testar

O que é o padrão Strategy

O Strategy é um padrão de projeto comportamental que resolve exatamente esse problema.

A ideia central é simples: encapsular comportamentos intercambiáveis atrás de uma interface comum.

  • você define o que precisa ser feito (interface)
  • cria várias formas de fazer isso (strategies)
  • escolhe qual usar em tempo de execução

Sem if/else espalhado.
Sem acoplamento desnecessário.

Estrutura do Strategy

Conceitualmente, temos três peças:

  • Strategy (interface) – define o contrato
  • Concrete Strategies – implementações do comportamento
  • Context – quem usa a strategy

Visualmente:

Context -> Strategy

   -------------------------
   |           |           |
StrategyA  StrategyB  StrategyC

Exemplo prático

Vamos imaginar um cenário simples: cálculo de taxa.

Interface

type TaxStrategy interface {
    Calculate(value float64) float64
}

Implementações

type BrazilTax struct{}

func (b *BrazilTax) Calculate(value float64) float64 {
    return value * 0.15
}
type USATax struct{}

func (u *USATax) Calculate(value float64) float64 {
    return value * 0.08
}

Context

type Order struct {
    Tax TaxStrategy
}

func (o *Order) FinalValue(value float64) float64 {
    return value + o.Tax.Calculate(value)
}

Uso

order := Order{Tax: &BrazilTax{}}
final := order.FinalValue(100)

Trocar a regra não exige mudar o Order. Basta trocar a strategy.

Registry de strategies

Em sistemas maiores, é comum usar um registry para centralizar as strategies disponíveis:

var registry = map[string]TaxStrategy{
    "br": &BrazilTax{},
    "us": &USATax{},
}

Isso facilita:

  • extensão do sistema
  • leitura do código
  • configuração por ambiente ou feature

Quando usar Strategy

Use Strategy quando:

  • ✅ Você tem variações de comportamento
  • ✅ Essas variações crescem com o tempo
  • ✅ Você quer eliminar if/else baseados em tipo, regra ou contexto
  • ✅ Testabilidade é importante

Quando NÃO usar

Nem tudo precisa de Strategy 👀

Evite quando:

  • ❌ Existe só uma implementação e nenhuma chance real de variação
  • ❌ A abstração adiciona mais complexidade do que resolve
  • ❌ O comportamento nunca muda

Padrão de projeto não é troféu — é ferramenta.

Erro comum ao usar Strategy

Um erro clássico é deixar a strategy conhecer o contexto errado, como ambiente:

if env == "qa" {
    // lógica especial
}

Se isso começa a aparecer, é sinal de que:

  • você precisa de strategies diferentes
  • ou de comportamentos injetáveis

Strategy boa é pura e focada em uma única responsabilidade.

Conclusão

O padrão Strategy é um dos padrões mais úteis no dia a dia, especialmente em sistemas que:

  • evoluem rápido
  • têm regras de negócio mutáveis
  • precisam ser fáceis de testar e manter

Se você sente que seu código está virando uma árvore de if/else, talvez não seja falta de esforço — talvez só esteja faltando uma boa Estratégia 😉

0 views
Back to Blog

Related posts

Read more »