
Strategy
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.
Problema
Seção intitulada “Problema”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).
Solução
Seção intitulada “Solução”O Strategy propõe:
- Definir uma interface Strategy com o método do algoritmo.
- Criar uma ConcreteStrategy para cada algoritmo.
- 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.
Estrutura (papéis)
Seção intitulada “Estrutura (papéis)”- 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
Exemplo completo em Java (didático)
Seção intitulada “Exemplo completo em Java (didático)”Strategy
Seção intitulada “Strategy”public interface EstrategiaFrete { double calcular(double peso);}Concrete Strategies
Seção intitulada “Concrete Strategies”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; }}Context
Seção intitulada “Context”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); }}Uso (cliente)
Seção intitulada “Uso (cliente)”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:
Pedidonão muda ao adicionar uma nova modalidade;- para criar
FreteExpresso, basta uma nova classeEstrategiaFrete; - a troca de comportamento acontece em tempo de execução.
Aplicabilidade (quando usar)
Seção intitulada “Aplicabilidade (quando usar)”Use Strategy quando:
- Existem vários algoritmos para a mesma tarefa e o cliente escolhe qual usar.
- A classe acumula
if/else/switchpara 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:
Comparatordo 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/elsegigantes.
Contras
Seção intitulada “Contras”- 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.
Relações com outros padrões
Seção intitulada “Relações com outros padrões”- 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
Functionou 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.