<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Davi Lopes</title>
    <description>The latest articles on DEV Community by Davi Lopes (@davi_lopes).</description>
    <link>https://dev.to/davi_lopes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3131467%2Fbc94a7f0-a75c-4284-9f17-55a1899b310c.png</url>
      <title>DEV Community: Davi Lopes</title>
      <link>https://dev.to/davi_lopes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davi_lopes"/>
    <language>en</language>
    <item>
      <title>Utilizando Strategy Pattern no Spring Boot</title>
      <dc:creator>Davi Lopes</dc:creator>
      <pubDate>Sun, 11 May 2025 16:44:21 +0000</pubDate>
      <link>https://dev.to/davi_lopes/utilizando-strategy-pattern-no-spring-boot-2nf3</link>
      <guid>https://dev.to/davi_lopes/utilizando-strategy-pattern-no-spring-boot-2nf3</guid>
      <description>&lt;p&gt;O Strategy Pattern é um dos padrões comportamentais (Behavioral Patterns) e tem como objetivo permitir a seleção dinâmica de algoritmos em tempo de execução. Ele define uma família de algoritmos encapsulados em classes distintas, todas com uma interface comum, e permite que o código cliente escolha qual deles utilizar sem conhecer os detalhes da implementação.&lt;/p&gt;

&lt;p&gt;Esse padrão é útil quando você tem múltiplas variações de um comportamento e quer tornar o sistema mais flexível e desacoplado. A ideia é separar o "o que fazer" (o comportamento) de "como fazer" (a implementação concreta), e poder trocar essa implementação sem alterar o restante do código.&lt;/p&gt;

&lt;p&gt;Vamos seguir para um exemplo prático para clarear as ideias. Digamos que em um processamento de um pedido de compra é aplicado um único desconto no valor total da compra.&lt;/p&gt;

&lt;p&gt;O que fazer = Aplicar Desconto no valor total.&lt;br&gt;
Como fazer = Aplicar desconto por cupom, por fidelidade ou primeira compra.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fynt1xkqzufafstnmtvrk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fynt1xkqzufafstnmtvrk.png" alt="Image description" width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Desta forma, definimos três formas de aplicar um desconto, agora podemos desenhar como ficará a estrutura do Strategy Pattern, separando o nosso caso de uso nos 4 conceitos abordados por esse pattern que são: &lt;strong&gt;Context, Strategy Interface, Concrete Strategies e Client Code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fri2jhhfty2svpfjqo4wy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fri2jhhfty2svpfjqo4wy.png" alt="Image description" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos destrinchar cada conceito mergulhando no código, por ordem de criação dos itens.&lt;/p&gt;
&lt;h1&gt;
  
  
  1. Strategy Interface
&lt;/h1&gt;

&lt;p&gt;Começar pela definição  do contrato que todas as Estratégias Concretas devem implementar, ou seja a Strategy Interface.&lt;/p&gt;

&lt;p&gt;Para nosso caso, a interface terá duas assinaturas de métodos, &lt;code&gt;canApply(Order order)&lt;/code&gt; que verificará a condição da estratégia ser executada e &lt;code&gt;apply(Order order)&lt;/code&gt; que será a aplicação do desconto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;DiscountStrategy&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;canApply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como parâmetro, é recebido a entidade Order com os seguintes atributos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
&lt;span class="nd"&gt;@Data&lt;/span&gt;
&lt;span class="nd"&gt;@NoArgsConstructor&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;couponCode&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;totalPrice&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;totalPriceWithDiscount&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;hasCouponCode&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;couponCode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;couponCode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  2. Concrete Strategies
&lt;/h1&gt;

&lt;p&gt;Em seguida, criaremos as classes concretas que implementam a Strategy Interface.&lt;/p&gt;

&lt;h5&gt;
  
  
  2.1 FirstPurchaseDiscount
&lt;/h5&gt;

&lt;p&gt;Essa é a classe que implementa as regras do desconto por primeira compra.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;canApply&lt;/code&gt; verifica se o usuário vinculado ao pedido possui a flag firstPurchase ativa.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;apply&lt;/code&gt; executa 2 ações:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Seta o campo &lt;code&gt;totalPriceWithDiscount&lt;/code&gt; da classe Order aplicando o desconto de 10% no valor total da compra.&lt;/li&gt;
&lt;li&gt;Desabilita o desconto chamando o método &lt;code&gt;disableFirstPurchaseDiscount()&lt;/code&gt; da &lt;code&gt;UserService&lt;/code&gt; passando o id do &lt;code&gt;User&lt;/code&gt; como parâmetro.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FirstPurchaseDiscount&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DiscountStrategy&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;canApply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isFirstPurchase&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setTotalPriceWithDiscount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTotalPrice&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;multiply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0.1"&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt; &lt;span class="c1"&gt;// 10% discount&lt;/span&gt;
        &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;disableFirstPurchaseDiscount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  2.2 CouponDiscount
&lt;/h5&gt;

&lt;p&gt;Essa é a classe que implementa as regras do desconto por cupom.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;canApply&lt;/code&gt; verifica se a &lt;code&gt;Order&lt;/code&gt; possui o campo couponCode preenchido a partir do método &lt;code&gt;hasCouponCode()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;apply&lt;/code&gt; executa 3 ações:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consulta o valor de desconto oferecido pelo cupom a partir da chamada do método &lt;code&gt;getDiscountByCouponCode(order.getCouponCode())&lt;/code&gt;, passando como parâmetro o código do cupom.&lt;/li&gt;
&lt;li&gt;Seta o campo &lt;code&gt;totalPriceWithDiscount&lt;/code&gt; da classe Order aplicando o desconto retornado pela consulta anterior.&lt;/li&gt;
&lt;li&gt;Desabilita o cupom de desconto para a conta chamando o método &lt;code&gt;disableCouponByUser(order.getCouponCode(), order.getUser());&lt;/code&gt;, passando como parâmetro o código do cupom e o user id.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CouponDiscount&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DiscountStrategy&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;CouponService&lt;/span&gt; &lt;span class="n"&gt;couponService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;canApply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasCouponCode&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

   &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;discountPercentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;couponService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDiscountByCouponCode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCouponCode&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setTotalPriceWithDiscount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTotalPrice&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;multiply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;discountPercentage&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;couponService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;disableCouponByUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCouponCode&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  2.3 LoyaltyDiscount
&lt;/h5&gt;

&lt;p&gt;Essa é a classe que implementa as regras do desconto por fidelidade.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;canApply&lt;/code&gt; verifica se o usuário vinculado ao pedido possui a flag LoyalCustomer ativa.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;apply&lt;/code&gt; executa 1 ação:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Seta o campo &lt;code&gt;totalPriceWithDiscount&lt;/code&gt; da classe Order aplicando o desconto de 5% no valor total da compra.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoyaltyDiscount&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DiscountStrategy&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;canApply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isLoyalCustomer&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setTotalPriceWithDiscount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTotalPrice&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;multiply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0.05"&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt; &lt;span class="c1"&gt;// 5% discount&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  3. Context
&lt;/h1&gt;

&lt;p&gt;O Context é a classe que mantém referência para umas lista de estratégias, seguindo a ideia de que o Context conhece as possíveis estratégias, mas não sabe qual será aplicada até o momento da execução.&lt;/p&gt;

&lt;p&gt;Então, agora criaremos essa classe, que em resumo, gerencia as estratégias da interface &lt;code&gt;DiscountStrategy&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DiscountApplyContext&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DiscountStrategy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;discountStrategyList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DiscountStrategy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;discountApply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;discountStrategyList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;discount&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;discount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;canApply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findFirst&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ifPresent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;discount&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;discount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  3.1 Como funciona:
&lt;/h5&gt;

&lt;p&gt;Com &lt;code&gt;@RequiredArgsConstructor&lt;/code&gt;, o Spring injeta automaticamente todas as dependências final no construtor — neste caso, uma lista de &lt;code&gt;DiscountStrategy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O Spring detecta e injeta todas as implementações da interface &lt;code&gt;DiscountStrategy&lt;/code&gt; disponíveis no contexto da aplicação, preenchendo a lista &lt;code&gt;discountStrategyList&lt;/code&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  3.2 Lógica do método &lt;code&gt;execute&lt;/code&gt;:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Recebe um objeto &lt;code&gt;Order&lt;/code&gt; como parâmetro.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Percorre a lista de estratégias de desconto (&lt;code&gt;discountStrategyList&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Para cada estratégia, chama o método &lt;code&gt;canApply(order)&lt;/code&gt; para verificar se ela é aplicável ao pedido.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ao encontrar a primeira estratégia aplicável, ela é capturada como um &lt;code&gt;Optional&amp;lt;DiscountStrategy&amp;gt;.&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Se nenhuma estratégia aplicável for encontrada (Optional vazio), o método encerra sem fazer nada.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Se uma estratégia for encontrada, chama-se &lt;code&gt;apply(order)&lt;/code&gt; para aplicar o desconto, nesse caso, apenas uma estratégia de desconto será aplicada.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  4. Client Code
&lt;/h1&gt;

&lt;p&gt;Por fim, temos o Client Code, que representa a parte do sistema responsável por utilizar o Context para executar alguma lógica baseada em estratégias. O client não conhece os detalhes internos das estratégias, apenas sabe que o Context possui a capacidade de executá-las de acordo com a situação.&lt;/p&gt;

&lt;p&gt;No exemplo abaixo, a classe &lt;code&gt;OrderPaymentService&lt;/code&gt; é responsável por processar o pagamento de um pedido. Antes de realizar o pagamento, o método &lt;code&gt;execute(order)&lt;/code&gt; chama &lt;code&gt;discountApplyContext.execute(order)&lt;/code&gt;, permitindo que uma estratégia de desconto apropriada seja aplicada ao pedido, caso exista.&lt;/p&gt;

&lt;p&gt;Desta forma, a classe &lt;code&gt;OrderPaymentService&lt;/code&gt; se enquandra como um Client, pois utiliza o Context(&lt;code&gt;DiscountApplyContext&lt;/code&gt;) para aplicação de uma estratégia no seu fluxo de código.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderPaymentService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;DiscountApplyContext&lt;/span&gt; &lt;span class="n"&gt;discountApplyContext&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;

        &lt;span class="n"&gt;discountApplyContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//Processing payment for order: " + order.getId());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;O Strategy Pattern é uma técnica eficaz para evitar estruturas complexas de if-else ou switch, promovendo um código mais limpo, modular e de fácil manutenção. Ao delegar a lógica de decisão para classes específicas, como fizemos com as estratégias de desconto, o código cliente não precisa se preocupar com as variações de comportamento. Por exemplo, se surgir uma nova regra de desconto, basta criar uma nova classe que implemente a interface DiscountStrategy e deixá-la disponível para o Spring — sem tocar na lógica do serviço principal.&lt;/p&gt;

&lt;p&gt;Essa abordagem facilita a escalabilidade da aplicação e torna o sistema mais preparado para mudanças futuras.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>java</category>
      <category>designpatterns</category>
    </item>
  </channel>
</rss>
