Usando o padrão strategy com o recurso enums do java
Implementação sem strategy
Supondo que você queira calcular os impostos sobre um determinado produto e pela lei idosos e estudantes possuem diferentes isenções de impostos (somente no exemplo) primeiro vamos implementar a função de calcular os impostos sem usar o stategy
public double calcularImpostoSemStrategy(double precoProduto, ImpostoTipo imposto){
if(imposto == ImpostoTipo.ESTUDANTES)
return precoProduto + (precoProduto * 0.15);
if(imposto == ImpostoTipo.IDOSOS)
return precoProduto + (precoProduto * 0.1);
return precoProduto + (precoProduto * 0.1);
}
Esta implementação pode até ser funcional, mas ela possui uma série de desvantagens, supondo que saiu uma lei que dá isenção de imposto para gestantes, neste caso eu teria que ir na classe de novo a adicionar mais um if, além de ferir o Open-Closed Principle do SOLID, o código ficará cheio de if´s alinhados e mais complicado de ler, para resolver isso usa-se o padrão strategy
O que é o padrão strategy
O padrão Strategy é uma forma de escrever programas que permite mudar o comportamento de um objeto sem precisar mudar a estrutura dele. Isso ajuda a deixar o código mais flexível e reutilizável, além de dividir melhor as responsabilidades das diferentes partes do programa.
Implementando o strategy
Para implementar o strategy primeiro vamos criar uma interface chamada "ImpostoStrategy", esta interface representa a abstração do imposto.
`
public interface ImpostoStartegy {
public double calcularImposto(double preco);
}
`
O conceito de inversão de dependências do SOLID sugere que uma classe dependa de uma abstração genérica, como uma interface ou classe abstrata, em vez de depender diretamente de uma classe concreta. Isso torna o código mais flexível e fácil de modificar.
public class ImpostoNormal implements ImpostoStartegy {
@Override
public double calcularImposto(double preco) { return preco * 0.2; }
}
//outras implementações ocultadas
Agora veja como a nossa função além de ficar mais sucinta, agora ao adicionarmos por exemplo o imposto gestante, basta criar uma classe e implementar a interface, assim obedecendo o Open-Closed Principle do SOLID
calcularImpostoStrategy(100,new ImpostoNormal());
public double calcularImpostoStrategy(double precoProducto, ImpostoStartegy strategy){
return precoProducto + strategy.calcularImposto(precoProducto);
}
Implementando usando enums
Ainda há como melhorar essa implementação usando o recurso enum do java, deixando o código ainda mais sucinto, pois irá ter menos classes no código, assim diminuindo sua complexidade.
public enum ImpostoTipo {
NORMAL{
@Override
double calcularImposto(double preco) {
return preco * 0.2;
}
},IDOSOS{
@Override
double calcularImposto(double preco) {
return preco * 0.1;
}
},ESTUDANTES{
@Override
double calcularImposto(double preco) {
return preco * 0.15;
}
};
abstract double calcularImposto(double preco);
}
calcularImpostoEnum(100,ImpostoTipo.IDOSOS);
public double calcularImpostoEnum(double precoProduto, ImpostoTipo impostoTipo){
return precoProduto + impostoTipo.calcularImposto(precoProduto);
}
Conclusão
O recurso Enum do Java é maravilhoso por permitir a definição de um conjunto fixo de valores constantes e nomeados em uma única classe, facilitando a legibilidade e manutenção do código. Além disso, os Enums podem ter comportamentos próprios, o que permite uma maior encapsulação de dados e redução de erros em tempo de execução. Com o recurso Enum, é possível ter mais clareza e consistência no código, tornando-o mais fácil de entender e manter.