Menu
Coddy logo textTech

Padrão Strategy

Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy — lição 55 de 70.

O padrão Strategy é um padrão 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. Em vez de codificar o comportamento de forma rígida, você injeta a estratégia desejada em um objeto.

O padrão consiste em três partes: uma interface de estratégia que define o contrato do algoritmo, classes de estratégia concretas que implementam diferentes comportamentos e uma classe de contexto que usa uma estratégia:

public interface IPaymentStrategy
{
    void Pay(decimal amount);
}

public class CreditCardPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via Credit Card");
}

public class PayPalPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via PayPal");
}

public class ShoppingCart
{
    private IPaymentStrategy _paymentStrategy;
    
    public void SetPaymentMethod(IPaymentStrategy strategy)
    {
        _paymentStrategy = strategy;
    }
    
    public void Checkout(decimal total)
    {
        _paymentStrategy.Pay(total);
    }
}

O contexto (ShoppingCart) não sabe qual método de pagamento está usando - ele apenas chama Pay() em qualquer estratégia que tenha sido fornecida:

var cart = new ShoppingCart();

cart.SetPaymentMethod(new CreditCardPayment());
cart.Checkout(99.99m);  // Pago 99.99 via Cartão de Crédito

cart.SetPaymentMethod(new PayPalPayment());
cart.Checkout(49.99m);  // Pago 49.99 via PayPal

O padrão Strategy elimina a lógica condicional complexa. Adicionar um novo método de pagamento significa criar uma nova classe que implementa IPaymentStrategy - nenhuma alteração é necessária em ShoppingCart. Isso torna seu código aberto para extensão, mas fechado para modificação.

challenge icon

Desafio

Fácil

Vamos construir uma calculadora de custos de envio usando o padrão Strategy. Diferentes métodos de envio possuem diferentes algoritmos de precificação, e seu sistema deve permitir a alternância entre eles em tempo de execução sem alterar a lógica central de processamento de pedidos.

Você organizará seu código em três arquivos:

  • ShippingStrategy.cs: Defina uma interface IShippingStrategy no namespace Shipping com um método CalculateCost(double weight) que retorna um double. Em seguida, crie três classes de estratégia concretas:
    • StandardShipping - calcula o custo como weight * 1.5
    • ExpressShipping - calcula o custo como weight * 3.0 + 5.0 (inclui uma taxa fixa expressa)
    • OvernightShipping - calcula o custo como weight * 5.0 + 10.0 (serviço premium com taxa base mais alta)
  • OrderProcessor.cs: Crie uma classe OrderProcessor no mesmo namespace. Esta é a sua classe de contexto que utiliza uma estratégia de envio. Ela deve ter:
    • Um campo privado para armazenar a IShippingStrategy atual
    • Um método SetShippingMethod(IShippingStrategy strategy) para alterar a estratégia de envio
    • Um método ProcessOrder(double weight) que utiliza a estratégia atual para calcular e retornar o custo de envio
  • Program.cs: Reúna tudo criando um OrderProcessor e demonstrando como você pode trocar as estratégias de envio em tempo de execução. O mesmo processador pode calcular custos usando diferentes algoritmos simplesmente alterando sua estratégia.

Você receberá duas entradas:

  • O tipo de método de envio: standard, express, ou overnight
  • O peso do pacote como um número decimal (ex: 4.5)

Crie um OrderProcessor, defina a estratégia de envio apropriada com base no tipo de entrada, processe o pedido e imprima o custo calculado.

Por exemplo, se as entradas forem express e 4.5, a saída deve ser:

18.5

Isso demonstra o poder do padrão Strategy - seu OrderProcessor não contém nenhuma lógica de cálculo de envio por si só. Ele simplesmente delega para qualquer estratégia que lhe tenha sido fornecida, facilitando a adição de novos métodos de envio (como DroneDelivery) sem modificar o processador!

Folha de consulta

O padrão Strategy é um padrão comportamental que define uma família de algoritmos, encapsula cada um em sua própria classe e os torna intercambiáveis em tempo de execução.

O padrão consiste em três partes:

  • Interface Strategy: define o contrato do algoritmo
  • Classes de estratégia concreta: implementam diferentes comportamentos
  • Classe de contexto: usa uma estratégia sem conhecer seus detalhes de implementação

Estrutura de exemplo:

// Interface Strategy
public interface IPaymentStrategy
{
    void Pay(decimal amount);
}

// Estratégias concretas
public class CreditCardPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via Credit Card");
}

public class PayPalPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via PayPal");
}

// Classe de contexto
public class ShoppingCart
{
    private IPaymentStrategy _paymentStrategy;
    
    public void SetPaymentMethod(IPaymentStrategy strategy)
    {
        _paymentStrategy = strategy;
    }
    
    public void Checkout(decimal total)
    {
        _paymentStrategy.Pay(total);
    }
}

Uso - alternando estratégias em tempo de execução:

var cart = new ShoppingCart();

cart.SetPaymentMethod(new CreditCardPayment());
cart.Checkout(99.99m);  // Paid 99.99 via Credit Card

cart.SetPaymentMethod(new PayPalPayment());
cart.Checkout(49.99m);  // Paid 49.99 via PayPal

Benefícios:

  • Elimina lógica condicional complexa
  • Aberto para extensão, fechado para modificação
  • Adicionar novas estratégias requer apenas a criação de novas classes, sem alterações no código existente

Experimente você mesmo

using System;
using Shipping;

class Program
{
    public static void Main(string[] args)
    {
        // Ler entrada
        string shippingType = Console.ReadLine();
        double weight = Convert.ToDouble(Console.ReadLine());

        // TODO: Create an OrderProcessor instance

        // TODO: Based on shippingType ("standard", "express", or "overnight"),
        // crie a estratégia de envio apropriada e defina-a no processor

        // TODO: Process the order and print the calculated 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