Pular para o conteúdo

Strategy é um padrão comportamental que resolve um problema comum: preciso que o mesmo processo possa executar algoritmos diferentes, escolhidos em tempo de execução, sem encher o código de if/else.

A ideia é simples:

  • você define uma interface de estratégia com o contrato do algoritmo;
  • cada algoritmo concreto vira uma classe de estratégia separada;
  • o contexto guarda uma estratégia e delega a ela o trabalho;
  • o cliente escolhe (e pode trocar) a estratégia sem mudar o contexto.

Imagine o módulo de frete de uma loja virtual. No começo, só existe uma modalidade:

public class CalculadoraFrete {
public double calcular(String modalidade, double peso) {
if (modalidade.equals("sedex")) {
return 20.0 + peso * 3.0;
} else if (modalidade.equals("pac")) {
return 10.0 + peso * 1.5;
} else if (modalidade.equals("retirada")) {
return 0.0;
}
throw new IllegalArgumentException("Modalidade inválida");
}
}

Funciona… até a loja precisar suportar:

  • novas modalidades (transportadora, expresso, agendada);
  • regras que dependem da região;
  • promoções com frete grátis.

O resultado é um if/else que cresce sem parar:

  • alto acoplamento a strings mágicas;
  • cada mudança toca um código já testado e grande;
  • difícil testar um algoritmo isoladamente;
  • viola o OCP (a classe precisa ser alterada a cada modalidade).

O Strategy propõe:

  1. Definir uma interface Strategy com o método do algoritmo.
  2. Criar uma ConcreteStrategy para cada algoritmo.
  3. Definir um Context, que:
    • guarda uma referência a uma Strategy;
    • recebe o pedido do cliente;
    • delega o cálculo à Strategy atual;
    • permite trocar a Strategy em runtime.

Assim, o contexto trabalha apenas com a abstração, e a decisão de “qual algoritmo” fica isolada.


  • Context: usa a Strategy e delega a ela (Pedido/Checkout)
  • Strategy: interface comum dos algoritmos (EstrategiaFrete)
  • ConcreteStrategy: cada algoritmo concreto (FreteSedex, FretePac, FreteRetirada)
  • Client: escolhe a estratégia e a entrega ao contexto

public interface EstrategiaFrete {
double calcular(double peso);
}
public class FreteSedex implements EstrategiaFrete {
public double calcular(double peso) {
return 20.0 + peso * 3.0;
}
}
public class FretePac implements EstrategiaFrete {
public double calcular(double peso) {
return 10.0 + peso * 1.5;
}
}
public class Pedido {
private EstrategiaFrete estrategia;
public Pedido(EstrategiaFrete estrategia) {
this.estrategia = estrategia;
}
public void setEstrategia(EstrategiaFrete estrategia) {
this.estrategia = estrategia;
}
public double totalFrete(double peso) {
return estrategia.calcular(peso);
}
}
public class App {
public static void main(String[] args) {
Pedido pedido = new Pedido(new FreteSedex());
System.out.println(pedido.totalFrete(2.0)); // 26.0
pedido.setEstrategia(new FretePac()); // troca em runtime
System.out.println(pedido.totalFrete(2.0)); // 13.0
}
}

Perceba o ponto importante:

  • Pedido não muda ao adicionar uma nova modalidade;
  • para criar FreteExpresso, basta uma nova classe EstrategiaFrete;
  • a troca de comportamento acontece em tempo de execução.

Use Strategy quando:

  • Existem vários algoritmos para a mesma tarefa e o cliente escolhe qual usar.
  • A classe acumula if/else/switch para decidir comportamento.
  • Os algoritmos precisam variar independentemente de quem os utiliza.
  • Você quer trocar o comportamento em runtime.

Exemplos comuns:

  • cálculo de frete, impostos e descontos;
  • métodos de pagamento (Pix, cartão, boleto);
  • ordenadores: Comparator do Java;
  • compressão, criptografia e formatos de arquivo.

  • OCP: novos algoritmos entram sem alterar o contexto.
  • SRP: cada algoritmo fica isolado na sua classe.
  • Troca de comportamento em runtime.
  • Desacopla o cliente das regras concretas.
  • Elimina if/else gigantes.

  • Mais classes: uma por algoritmo.
  • O cliente precisa conhecer as estratégias disponíveis para escolher.
  • Para um algoritmo único e estável, o contexto extra é overengineering.
  • A passagem de dados entre contexto e estratégia exige cuidado.

  • State: também delega a um objeto, mas no State a própria estratégia muda de estado e troca o comportamento sozinha.
  • Bridge: o Bridge separa abstração × plataforma; o Strategy apenas troca o algoritmo de uma tarefa.
  • Strategy como função: em Java moderno, uma Function ou um lambda pode substituir a interface. O padrão continua o mesmo, com menos classes.

  • Strategy = encapsule uma família de algoritmos intercambiáveis.
  • Objetivo principal: desacoplar o contexto do algoritmo concreto.
  • Ganho prático: trocar e estender comportamentos sem tocar no contexto.