Skip to content

Padrão Strategy

E ai pessoal, tudo bom?

Faz tempo que eu não posto aqui, mas agora espero postar com mais frequência.

Hoje vou falar de um assunto importante, padrões de projeto. E hoje o padrão discutido será o Strategy. O que farei primeiro é passar o conceito do padrão e algumas pesquisas que encontrei na internet sobre o mesmo e por ultimo irei demonstrar a forma para aplicar o padrão perante um exemplo.

Pesquisando na Wikipédia a definição do padrão Strategy é a seguinte: O padrão Strategy permite definir novas operações sem alterar as classes dos elementos sobre os quais opera. Definir uma família de algoritmos e encapsula cada algoritmo como uma classe, permitindo assim que elas possam ter trocados entre si. Este padrão permite que o algoritmo possa variar independentemente dos clientes que o utilizam.

Nas minhas palavras eu gosto de falar que este padrão define estratégia de família de algoritmos para ser abstraído em um contexto.

No site macoratti.net encontrei os cenários onde o padrão pode ser aplicado.

  1. Você tem um método que é aplicado em diferentes situações nas quais é exigido um comportamento específico;
  2. Você tem uma família de classes de estruturas parecidas mas que diferem no seu comportamento;
  3. Você tem uma classe que apresenta métodos muito complexos com múltiplos comandos condicionais (if/else);
  4. Você tem um algoritmo complexo que utiliza uma estrutura de dados que não precisa ser conhecida por quem vai utilizar o algoritmo;
  5. Você tem operações comuns a uma série de objetos de classes diferentes com pequenas variações de comportamento;

Todos estes pontos são exemplos onde podemos aplicar o padrão. Mas o 3° item para min talvez  seja o mais forte. Pensando nisso montei um exemplo para aplicação do padrão.

Strategy

O caso de uso é simples, calcular o desconto salarial do funcionário e a regra é dado abaixo:

  • Se o funcionário ganhar menos que R$ 1000,00 deverá ter 10% de desconto.
  • Se o funcionário ganhar até R$ 2000,00 deverá ter 15% de desconto.
  • Se o funcionário ganhar maior que R$ 2000,00 deverá ter 20% de desconto.

No UML acima é possível visualizar que foram criadas 3 estratégias (operações) de cálculos de desconto. Note que o nome das classes descrevem a regra do calculo e todas elas herdam da interface ICalculoDesconto e o que elas tem em comum é o método calcular que recebe o salário, mas o que difere entre elas é a implementação de cada uma, ou seja, o calculo do desconto do salário. A classe funcionário (context) que irá utilizar uma estratégia tem um objeto do tipo ICalculoDesconto.

[sourcecode language=”csharp”]
public interface ICalculoDesconto
{
Decimal Calcular(decimal salario);
}
[/sourcecode]

 

[sourcecode language=”csharp”]
public class Funcionario
{
public string Nome { get; set; }
public DateTime DataNascimento { get; set; }
public Decimal Salario { get; set; }
private ICalculoDesconto _calculoDesconto;

public Funcionario(ICalculoDesconto calculoDesconto)
{
_calculoDesconto = calculoDesconto;
}

public Decimal CalcularDesconto()
{
return _calculoDesconto.Calcular(this.Salario);
}
}
[/sourcecode]

 

[sourcecode language=”csharp”]
public class DescontoMenorQue1000 : ICalculoDesconto
{
public decimal Calcular(decimal salario)
{
return salario – salario * (decimal) 0.10;
}
}
[/sourcecode]

 

[sourcecode language=”csharp”]
public class DescontoAte2000 : ICalculoDesconto
{
public decimal Calcular(decimal salario)
{
return salario – salario * (decimal) 0.15;
}
}
[/sourcecode]

 

[sourcecode language=”csharp”]
public class DescontoMaiorQue2000 : ICalculoDesconto
{
public decimal Calcular(decimal salario)
{
return salario – salario*(decimal) 0.20;
}
}
[/sourcecode]

 

[sourcecode language=”csharp”]
//Cliente utilizando
var funcionario1 = new Funcionario(new DescontoMenorQue1000()) {Salario = 800};
funcionario1.CalcularDesconto();
var funcionario2 = new Funcionario(new DescontoAte2000()) {Salario = 1200};
funcionario2.CalcularDesconto();
var funcionario3 = new Funcionario(new DescontoMaiorQue2000()) {Salario = 2200};
funcionario3.CalcularDesconto();
[/sourcecode]
O código acima mostra como é o funcionamento do padrão Strategy. O objeto funcionário faz o calculo do desconto sem saber da regra, apenas utiliza uma estratégia em tempo de execução que foi passada através do construtor e no método CalcularDesconto() executa a operação. Nada disso necessariamente precisaria ser criado, no próprio método  da classe funcionário poderia existir os if/else para calcular o desconto, mas aplicando o padrão Strategy a solução ficou bem mais organizada. Se uma regra de desconto passar por manutenção não sofre o risco de acidentalmente as outras regras serem alterada.

O que gosto particularmente nesse padrão é que caso amanhã ou depois uma nova regra de desconto seja criada não é a classe Funcionário que será alterada e sim criada uma nova classe do grupo de calculo de desconto. Como qualquer outro padrão de projeto, Strategy é ótimo para resolver problemas igual ao exemplo, mas devemos sempre ter a cautela em utilizar em todo tipo de cenário.

Pessoal, esse foi o padrão Strategy e espero que tenha gostado.

Abraços e até o próximo post.

Fontes:

http://www.tiagorolim.com/2009/06/padrao-de-projetos-strategy-na-pratica.html
http://www.macoratti.net/08/08/net_stgy.htm
http://pt.wikipedia.org/wiki/Strategy

Published inQualidade de software

Be First to Comment

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *