Publicado originalmente em: http://blog.ivanqueiroz.com/2017/01/revisando-padroes-java-8-o-padrao-strategy.html
Esse post será o início de uma série o qual vou tentar explicar os padrões de projeto utilizando as novidades do Java 8, se visitou esse assunto espero que já conheça os conceitos de orientação a objetos, a linguagem java e Padrões de Projeto.
Esse post será o início de uma série o qual vou tentar explicar os padrões de projeto utilizando as novidades do Java 8, se visitou esse assunto espero que já conheça os conceitos de orientação a objetos, a linguagem java e Padrões de Projeto.
"O conceito de estratégia, em grego strateegia, em latim strategi, em francês stratégie..."
Capitão Nascimento (Filme Tropa de Elite).
Strategy
É um padrão comportamental utilizado quando uma classe possui muitos algoritmos que tem o mesmo propósito e que podem ser alternados na lógica da aplicação. A execução do algoritmo fica sob responsabilidade de uma instância que compõe a classe principal.
Aplicabilidade
Use o padrão Strategy quando:
- muitas classes relacionadas diferem somente no seu comportamento. As estratégias fornecem uma maneira de configurar uma classe comum dentre muitos comportamentos;
- você necessita de variantes de um algoritmo. Por exemplo, pode definir algoritmos que refletem diferentes soluções de compromisso entre espaço/ tempo. As estratégias podem ser usadas quando essas variantes são implementadas como uma hierarquia de classes de algoritmos;
- um algoritmo usa dados dos quais os clientes não deveriam ter conhecimento. Use o padrão Strategy para evitar a exposição das estruturas de dados complexas, específicas do algoritmo;
- uma classe define muitos comportamentos, e estes aparecem em suas operações como múltiplos comandos condicionais da linguagem. Em vez de usar muitos comandos condicionais, mova os ramos condicionais relacionados para a sua própria classe Strategy.
Implementação
Para exemplo criei uma classe AgenteSecreto que irá consumir os algoritmos de estratégia, possui um método que executa a ação (no caso combater) e outro método que muda a estratégia em tempo de execução:
}
A interface que define o algoritmo de execução:
}
Criei três implementações da interface com os algoritmos: EstrategiaEngenharia, EstrategiaLinhaDeFrente e EstrategiaSuporte. Agora vamos a Implementação do programa.
Antes do Java 8
Após definir a interface que encapsula o algoritmo só precisamos instanciar a estratégia que queremos utilizar, passando por construtor para a classe AgenteSecreto ou chamando o método mudarEstrategia():
LOGGER.info("Inimigos localizados dentro do forte!");
AgenteSecreto agente = new AgenteSecreto(new EstrategiaLinhaDeFrente());
agente.combater();
LOGGER.info("Inimigos efetuando disparos!");
agente.mudarEstrategia(new EstrategiaEngenharia());
agente.combater();
LOGGER.info("Equipe sendo alvejada!");
agente.mudarEstrategia(new EstrategiaSuporte());
agente.combater();
Após o Java 8
A partir do Java 8 e o suporte a programação funcional, podemos utilizar novas sintaxes para alterar os algoritmos.
Lambdas
Com o suporte a Lambdas, podemos "passar" a implementação do algoritmo diretamente para o construtor de AgenteSecreto ou ao método mudarEstrategia():
LOGGER.info("Java 8 Lambdas");
LOGGER.info("Inimigos localizados dentro do forte!");
agente = new AgenteSecreto(() -> LOGGER.info("Segurar escudo e invadir."));
agente.combater();
LOGGER.info("Inimigos efetuando disparos!");
agente.mudarEstrategia(() -> LOGGER.info("Armar torreta, jogar granadas de efeito e plantar minas."));
agente.combater();
LOGGER.info("Equipe sendo alvejada!");
agente.mudarEstrategia(()-> LOGGER.info("Esperar feridos e ajudar."));
agente.combater();
A vantagem dessa abordagem é de não termos que criar uma classe para algoritmos pequenos, diminuindo o número de classes do projeto.
Referência a métodos
Outra facilidade da programação funcional do Java 8 é o de referenciar métodos ou o chamado Method Reference, essa facilidade é interessante quando a expressão lâmbda chama métodos já existentes, para exemplo criei em cada implementação de estratégia um método estático que realiza em si a ação requerida, com isso é possível utilizar a sintaxe do method reference e "passar" os métodos diretamente para o AgenteSecreto:
LOGGER.info("Java 8 Method References");
LOGGER.info("Inimigos localizados dentro do forte!");
agente.mudarEstrategia(EstrategiaLinhaDeFrente::combaterComoLinhaDeFrente);
agente.combater();
LOGGER.info("Inimigos efetuando disparos!");
agente.mudarEstrategia(EstrategiaEngenharia::combaterComoEngenheiro);
agente.combater();
LOGGER.info("Equipe sendo alvejada!");
agente.mudarEstrategia(EstrategiaSuporte::combaterComoSuporte);
agente.combater();
Essa abordagem é interessante para os casos em que temos expressões lambda que apenas chamam outros métodos. Com ela deixamos o código mais legível além de chamarmos diretamente o método de ação.
Executando
Ao executarmos a aplicação temos o seguinte resultado:
padroes.strategy.Aplicacao - Inimigos localizados dentro do forte!
padroes.strategy.EstrategiaLinhaDeFrente - Segurar escudo e invadir.
padroes.strategy.Aplicacao - Inimigos efetuando disparos!
padroes.strategy.EstrategiaEngenharia - Armar torreta, jogar granadas de efeito e plantar minas.
padroes.strategy.Aplicacao - Equipe sendo alvejada!
padroes.strategy.EstrategiaSuporte - Esperar feridos e ajudar.
padroes.strategy.Aplicacao - Java 8 Lambdas
padroes.strategy.Aplicacao - Inimigos localizados dentro do forte!
padroes.strategy.Aplicacao - Segurar escudo e invadir.
padroes.strategy.Aplicacao - Inimigos efetuando disparos!
padroes.strategy.Aplicacao - Armar torreta, jogar granadas de efeito e plantar minas.
padroes.strategy.Aplicacao - Equipe sendo alvejada!
padroes.strategy.Aplicacao - Esperar feridos e ajudar.
padroes.strategy.Aplicacao - Java 8 Method References
padroes.strategy.Aplicacao - Inimigos localizados dentro do forte!
padroes.strategy.EstrategiaLinhaDeFrente - Segurar escudo e invadir.
padroes.strategy.Aplicacao - Inimigos efetuando disparos!
padroes.strategy.EstrategiaEngenharia - Armar torreta, jogar granadas de efeito e plantar minas.
padroes.strategy.Aplicacao - Equipe sendo alvejada!
padroes.strategy.EstrategiaSuporte - Esperar feridos e ajudar.
Vantagens e desvantagens do Strategy
Em outras fontes você irá encontrar diversas vantagens e desvantagens sobre o padrão, para mim as principais vantagens são:
- criar novos algoritmos com modificações mínimas da aplicação;
- poder alterar os algoritmos em tempo de execução;
- diminuição de estruturas condicionais na classe cliente.
Já as desvantagens:
- aumento no número de classes;
- aumento na complexidade de criação do objeto, já que a instância da dependência precisa ser criada e configurada.
Finalizando
Na versão 8 a linguagem Java trouxe ótimas novidades que ajudam bastante no desenvolvimento de soluções de código mais simples e legíveis. O suporte a programação funcional trás um novo paradigma para os desenvolvedores que utilizam a linguagem, cabe a nós avaliar e escolher a melhor forma de aproveitá-la. Um forte abraço e até a próxima.
1 comentários:
Parabéns pelo post Ivan. Muito bem explicado.
Postar um comentário