1
resposta

[Sugestão] Exemplo de Chain Of Responsibility e Template Method

Interface de Desconto

 public interface IDesconto
    {
        IDesconto Proximo { get; set; }
        public double CalculaDesconto(Orcamento orcamento);
    }

Template com comportamento para o Desconto.

  1. Recebe um desconto no construtor para ser o próximo (se necessário).
  2. comportamento para verificar condição válida de aplicação do desconto
  3. comportamento para calcular o valor do desconto.
public abstract class TemplateDesconto : IDesconto
    {
        public IDesconto? Proximo { get; set; }


        public TemplateDesconto (IDesconto? proximo = null)
        {
            this.Proximo = proximo;
        }

        public double CalculaDesconto(Orcamento orcamento)
        {
            if (CondicaoValidaParaDesconto(orcamento))
            {
                return GeraValorDesconto(orcamento);
            }

            if (Proximo != null)
            {
                return Proximo.CalculaDesconto(orcamento);
            }

            return 0;
        }

        protected abstract double GeraValorDesconto(Orcamento orcamento);
        protected abstract bool CondicaoValidaParaDesconto(Orcamento orcamento);
    }

Exemplo de desconto por valor:

  1. Recebe o valor que você quer comparar
  2. Porcentagem para calculo
  3. se necessário um IDesconto para ser o próximo.
  4. ValorMaximo (caso exista um Próximo e seja um desconto por valor também)
  public class DescontoPorValor : TemplateDesconto
    {
        double Porcentagem { get; set; }

        double Valor { get; set; }
        double ValorMax { get; set; }

        public DescontoPorValor(double valor, double porcentagem, IDesconto proximo = null, double valorMax = 0)
            : base(proximo)
        {
            this.Valor = valor;
            this.Porcentagem = porcentagem;
            this.ValorMax = valorMax;
        }


        protected override bool CondicaoValidaParaDesconto(Orcamento orcamento)
        {
           if (ValorMax != 0)
            {
                return orcamento.Valor > this.Valor && orcamento.Valor <= this.ValorMax;
            }

           return orcamento.Valor > this.Valor;
        }

        protected override double GeraValorDesconto(Orcamento orcamento)
        {
            return orcamento.Valor * (this.Porcentagem / 100);
        }
    }

Calculador de descontos: Faz a instância de 3 descontos por valor, passando como parâmetro o valor mínimo, a porcentagem de desconto, o próximo desconto e o valor máximo.

Nesse exemplo se o valor estiver entre 500 e 1000 o desconto será de 10%....

Entre 1000 e 2000 - Será de 20%...

Acima de 2000 - 25%..

 public class CalculadorDescontosTm
    {
        public double CalculaDesconto(Orcamento orcamento)
        {
            IDesconto desconto3 = new DescontoPorValor(2000, 25);
            IDesconto desconto2 = new DescontoPorValor(1000, 20, desconto3, 2000);
            IDesconto desconto1 = new DescontoPorValor(500, 10, desconto2, 1000);

            return desconto1.CalculaDesconto(orcamento);
        }
     }

Program.CS para execução:

Console.WriteLine("Calculador de descontos");

Console.WriteLine("Gerando um orçamento de teste");

Orcamento orcamento = new Orcamento();
orcamento.AdicionaItem(new Item("RTX 2060 Super", 1000));
orcamento.AdicionaItem(new Item("Placa mãe", 600));
orcamento.AdicionaItem(new Item("Kit Mouse e Teclado", 200));

Console.WriteLine($"Orcamento gerado com valor de {orcamento.Valor} com total de {orcamento.QuantidadeItens()} itens.");

Console.WriteLine("Aplicando descontos....");

CalculadorDescontosTm calculador = new CalculadorDescontosTm();

Console.WriteLine($"Desconto gerado: {calculador.CalculaDesconto(orcamento)}");

console do windows com fundo preto mostrando o resultado da operacao

Dessa forma podemos implementar outros tipos de descontos, herdando do TemplateDesconto e implementando apenas os métodos CondicaoValidaParaDesconto e GeraValorDesconto;

 public class DescontoPorItens : TemplateDesconto
    {
        protected override bool CondicaoValidaParaDesconto(Orcamento orcamento)
        {
            return orcamento.QuantidadeItens() > 10;
        }

        protected override double GeraValorDesconto(Orcamento orcamento)
        {
            return orcamento.Valor * 0.05;
        }
    }
1 resposta

Excelente! Que bom que agora já podemos declarar propriedades nas interfaces.

A tecnologia evolui, e até os cursos mais teóricos como esse precisam ser atualizados...