Design Patterns - 1 - Strategy (C#)
Tags: designpatterns, csharp, codequality, refactorit
Published: 2022-10-13 23:28:36

Padrões de projeto, ou design patterns, são bem importantes para escrever códigos limpos, manuteníveis, legíveis e bem estruturados de acordo com cada situação, ou seja, para trazer soluções elegantes para problemas recorrentes. 

Para iniciar o estudo desses padrões, temos o padrão _Strategy_, um padrão comportamental que traz uma estratégia para lidar com a repetição e reaproveitamento de algoritmos em comum a diversas classes. Para isto, utilizamos interfaces que possuem uma definição desses métodos comuns e um conjunto de classes que implementam essa interface, concentrando toda a manipulação desse método no objeto e não tendo que criar código repetido em cada classe criada.

Para que fique mais claro, temos como exemplo uma calculadora de impostos, onde os métodos de cada imposto tem uma mesma estrutura, mudando apenas a taxa de acordo com o imposto escolhido. Para evitar que crie-se uma estrutura gigantesca com várias condicionais ou métodos, separamos os impostos em classes e criamos uma interface com a definição do método de cálculo do imposto recebendo o orçamento como parâmetro. As classes então implementariam a interface, sendo possível criar um único método na CalculadoraDeImpostos, lidando com o valor de acordo com a variância do método com o imposto definido.

Temos então a definição das classes de Impostos:

**ICMS**

```
using System;
namespace DesignPatterns.Impostos
{
    public class ICMS : Imposto
    {
        public double Calcula(Orcamento orcamento)
        {
            return orcamento.Valor * 0.1;
        }
    }
}
```

**ISS**
```
using System;
namespace DesignPatterns.Impostos
{
    public class ISS : Imposto
    {
        public double Calcula(Orcamento orcamento)
        {
            return orcamento.Valor * 0.6;
        }
    }
}
```

Concentradas em um diretório de impostos para manter a organização e facilitar a leitura/manipulação.

A interface **Imposto** traz então a definição do método Calcula, comum entre os diversos impostos:

**Imposto**
```
using System;
namespace DesignPatterns
{
    public interface Imposto
    {
        double Calcula(Orcamento orcamento);
    }
}
```

Na classe da calculadora de impostos, temos o método que recebe o orçamento e o tipo de imposto e chama o método Calcula informando o orçamento como parâmetro.

**CalculadorDeImpostos**
```
using System;
using DesignPatterns.Impostos;

namespace DesignPatterns
{
    public class CalculadoraDeImpostos
    {
        public void RealizaCalculo(Orcamento orcamento, Imposto imposto)
        {
            double valor = imposto.Calcula(orcamento);
            Console.WriteLine(valor);
        }
    }
}
```

Na classe orçamento, que recebe o valor,  temos:

**Orçamento**
```
using System;
namespace DesignPatterns
{
    public class Orcamento
   {
        public double Valor { get; private set; }

        public Orcamento(double valor)
        {
            this.Valor = valor;
        }
    }
}
```

E então na classe Program, instanciamos um orçamento e um imposto e calculamos e realizamos o calculo informando essas propriedades:

**Program**
```
// See https://aka.ms/new-console-template for more information
using DesignPatterns;
using DesignPatterns.Impostos;

Orcamento orcamento = new Orcamento(500.00);

Imposto imposto = new ICMS();

CalculadorDeImpostos calculador = new CalculadorDeImpostos();

calculador.RealizaCalculo(orcamento, imposto);
```

A resposta no terminal será: 50.00.

Então, o padrão comportamental Strategy permite que uma família de algoritmos similares se conversem, mas sejam separados em classes, tornando o código desacoplado e bem distribuído.