Menu
Coddy logo textTech

Padrão Strategy

Parte da seção Programação Orientada a Objetos do Journey de PHP da Coddy — lição 74 de 91.

O Padrão Strategy é um padrão de projeto comportamental que permite definir uma família de algoritmos, encapsular cada um em sua própria classe e torná-los intercambiáveis em tempo de execução. O objeto que utiliza a estratégia não precisa saber qual algoritmo está executando.

Imagine um carrinho de compras que pode aplicar diferentes estratégias de desconto. Em vez de codificar rigidamente a lógica de desconto com condicionais, você define cada desconto como uma classe separada:

<?php
interface DiscountStrategy {
    public function calculate(float $total): float;
}

class NoDiscount implements DiscountStrategy {
    public function calculate(float $total): float {
        return $total;
    }
}

class PercentageDiscount implements DiscountStrategy {
    public function __construct(private int $percent) {}
    
    public function calculate(float $total): float {
        return $total - ($total * $this->percent / 100);
    }
}

class FixedDiscount implements DiscountStrategy {
    public function __construct(private float $amount) {}
    
    public function calculate(float $total): float {
        return max(0, $total - $this->amount);
    }
}

A classe de contexto aceita qualquer estratégia e delega o cálculo:

<?php
class ShoppingCart {
    public function __construct(private DiscountStrategy $discount) {}
    
    public function setDiscount(DiscountStrategy $discount): void {
        $this->discount = $discount;
    }
    
    public function checkout(float $total): float {
        return $this->discount->calculate($total);
    }
}

$cart = new ShoppingCart(new NoDiscount());
echo $cart->checkout(100) . "\n";

$cart->setDiscount(new PercentageDiscount(20));
echo $cart->checkout(100);

Saída:

100
80

O Padrão Strategy se destaca quando você tem múltiplas formas de realizar uma operação e deseja alternar entre elas sem modificar a classe que as utiliza. Adicionar um novo tipo de desconto significa criar uma nova classe, sem tocar no código existente.

challenge icon

Desafio

Fácil

Vamos construir uma calculadora de custos de envio usando o Strategy Pattern. Diferentes métodos de envio têm diferentes regras de preço — o envio padrão cobra uma taxa fixa, o envio expresso adiciona uma porcentagem e o envio noturno combina ambos. O Strategy Pattern permite que você troque esses cálculos sem alterar o código que os utiliza.

Você organizará seu código em quatro arquivos:

  • ShippingStrategy.php — Crie uma interface ShippingStrategy que define o contrato para todos os métodos de envio. Ela deve ter um método calculate(float $weight): float que recebe o peso do pacote e retorna o custo de envio.
  • ShippingMethods.php — Inclua o arquivo ShippingStrategy e crie três classes que implementam a interface:
    • StandardShipping — Cobra uma taxa fixa de $5.00 independentemente do peso
    • ExpressShipping — Cobra $2.00 por quilograma (multiplique o peso por 2)
    • OvernightShipping — Cobra uma taxa base de $10.00 mais $3.00 por quilograma
  • ShippingCalculator.php — Inclua o arquivo ShippingStrategy e crie uma classe ShippingCalculator que atua como o contexto. Sua calculadora deve:
    • Aceitar uma ShippingStrategy em seu construtor (use promoção de construtor)
    • Ter um método setStrategy(ShippingStrategy $strategy): void para alterar o método de envio em tempo de execução
    • Ter um método calculateCost(float $weight): float que delega para a estratégia atual
  • main.php — Inclua os arquivos ShippingMethods e ShippingCalculator. Você receberá duas entradas: um tipo de envio ("standard", "express", ou "overnight") e o peso de um pacote.

    Crie um ShippingCalculator começando com StandardShipping. Com base na entrada do tipo de envio, use setStrategy() para mudar para o método de envio apropriado. Em seguida, calcule o custo para o peso fornecido e exiba o resultado formatado com duas casas decimais.

    A saída deve ser: Shipping cost: $[cost]

Este desafio demonstra como o Strategy Pattern torna seu sistema de envio flexível — adicionar um novo método de envio como SameDayShipping requer apenas a criação de uma nova classe que implementa a interface, sem tocar na calculadora ou nos métodos de envio existentes.

Experimente você mesmo

<?php
require_once 'ShippingMethods.php';
require_once 'ShippingCalculator.php';

// Ler a entrada
$shippingType = trim(fgets(STDIN));
$weight = floatval(fgets(STDIN));

// TODO: Criar um ShippingCalculator começando com StandardShipping

// TODO: Com base no tipo de envio inserido ("standard", "express" ou "overnight"),
// use setStrategy() para mudar para o método de envio apropriado

// TODO: Calcular o custo para o peso fornecido

// TODO: Imprimir o resultado formatado com duas casas decimais
// Formato de saída: Shipping cost: $[cost]

?>
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos