Patrón Strategy: Cálculo de Precios con Descuentos en C++

El patrón Strategy permite encapsular diferentes algoritmos de cálculo de precios e intercambiarlos dinámicamente según la promoción aplicable. Un caso típico es un sistema de cobro donde el importe final depende del tipo de oferta activa: precio estándar, descuento porcentual o devolución por gasto mínimo.

La estructura se compone de tres elementos principales:

  • Interfaz de estrategia: define el contrato común para todos los algoritmos de cálculo.
  • Estrategias concretas: implementan cada regla de negocio específica.
  • Contexto: actúa como intermediario entre el cliente y las estrategias, seleccionando la apropiada en tiempo de ejecución.

Interfaz de estrategia

enum class PricingMode
{
    STANDARD,
    PERCENTAGE_DISCOUNT,
    CASHBACK_REWARD
};

class PaymentStrategy
{
public:
    virtual ~PaymentStrategy() = default;
    virtual double calculateTotal(double baseAmount) const = 0;
};

Estrategias concretas

class StandardPayment : public PaymentStrategy
{
public:
    double calculateTotal(double baseAmount) const override
    {
        return baseAmount;
    }
};
class DiscountPayment : public PaymentStrategy
{
public:
    explicit DiscountPayment(double rate) : discountRate_(rate) {}

    double calculateTotal(double baseAmount) const override
    {
        return baseAmount * discountRate_;
    }

private:
    double discountRate_;
};
class CashbackPayment : public PaymentStrategy
{
public:
    CashbackPayment(double threshold, double cashback)
        : threshold_(threshold), cashback_(cashback) {}

    double calculateTotal(double baseAmount) const override
    {
        if (threshold_ < 1e-6)
            return baseAmount;

        int rewardUnits = static_cast<int>(baseAmount / threshold_);
        return baseAmount - rewardUnits * cashback_;
    }

private:
    double threshold_;
    double cashback_;
};

Clase de contexto

#include <memory>

class PricingContext
{
public:
    explicit PricingContext(PricingMode mode)
    {
        switch (mode)
        {
        case PricingMode::PERCENTAGE_DISCOUNT:
            strategy_ = std::make_unique<DiscountPayment>(0.8);
            break;
        case PricingMode::CASHBACK_REWARD:
            strategy_ = std::make_unique<CashbackPayment>(300.0, 100.0);
            break;
        case PricingMode::STANDARD:
        default:
            strategy_ = std::make_unique<StandardPayment>();
            break;
        }
    }

    double computeFinal(double baseAmount) const
    {
        return strategy_->calculateTotal(baseAmount);
    }

private:
    std::unique_ptr<PaymentStrategy> strategy_;
};

Ejemplo de uso

#include <iostream>

int main()
{
    PricingContext standardCtx(PricingMode::STANDARD);
    PricingContext discountCtx(PricingMode::PERCENTAGE_DISCOUNT);
    PricingContext cashbackCtx(PricingMode::CASHBACK_REWARD);

    std::cout << standardCtx.computeFinal(600) << std::endl;  // 600
    std::cout << discountCtx.computeFinal(600) << std::endl;  // 480
    std::cout << cashbackCtx.computeFinal(600) << std::endl;  // 400

    return 0;
}

El patrón Strategy elimina las estructuras condicionales dispersas por el código. Cada regla de promoción reside en su propia clase, lo que facilita añadir nuevas estrategias sin modificar las existentes ni el contexto. La selección de la estrategia puede delegarse a una fábrica o inyectarse directamente, según la complejidad del sistema.

Etiquetas: Strategy Pattern C++ design patterns object-oriented programming

Publicado el 7-17 03:49