<?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: Leticia Reis</title>
    <description>The latest articles on DEV Community by Leticia Reis (@leticiareizz).</description>
    <link>https://dev.to/leticiareizz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4115701%2F0b669ecb-1b32-4dcf-a184-433899081531.webp</url>
      <title>DEV Community: Leticia Reis</title>
      <link>https://dev.to/leticiareizz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/leticiareizz"/>
    <language>en</language>
    <item>
      <title>Strategy Pattern em Java: Isolando Regras de Cálculo Fiscal em um Sistema B2B</title>
      <dc:creator>Leticia Reis</dc:creator>
      <pubDate>Tue, 08 Sep 2026 13:23:19 +0000</pubDate>
      <link>https://dev.to/leticiareizz/strategy-pattern-em-java-isolando-regras-de-calculo-fiscal-em-um-sistema-b2b-2h4j</link>
      <guid>https://dev.to/leticiareizz/strategy-pattern-em-java-isolando-regras-de-calculo-fiscal-em-um-sistema-b2b-2h4j</guid>
      <description>&lt;p&gt;&lt;strong&gt;Como separar regras de negócio que mudam em ritmos diferentes — e por que o &lt;code&gt;switch&lt;/code&gt; é o lugar errado para elas.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;O &lt;strong&gt;Strategy&lt;/strong&gt; é um Padrão de Projeto &lt;strong&gt;Comportamental&lt;/strong&gt;, catalogado originalmente pela Gang of Four. Padrões comportamentais tratam de como objetos se comunicam e distribuem responsabilidades entre si — diferente dos criacionais, que tratam de como objetos são instanciados, e dos estruturais, que tratam de como objetos se compõem.&lt;/p&gt;

&lt;p&gt;A definição formal é curta: o Strategy encapsula uma família de algoritmos intercambiáveis, cada um em sua própria classe, e permite que o algoritmo varie independentemente do cliente que o utiliza.&lt;/p&gt;

&lt;p&gt;A definição prática é ainda mais curta: &lt;strong&gt;é o padrão que transforma a pergunta "qual regra eu aplico agora?" de uma estrutura condicional em uma escolha de objeto.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  O problema: o &lt;code&gt;switch&lt;/code&gt; que ninguém quer tocar
&lt;/h2&gt;

&lt;p&gt;Todo sistema que cresce acumula um método específico. Ele começa com dois casos, ganha um terceiro em uma sprint apertada e, alguns anos depois, tem centenas de linhas e um comentário do tipo &lt;code&gt;// não mexer sem falar com o time de faturamento&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O sintoma visível é feio, mas o sintoma não é o problema. O problema real é &lt;strong&gt;acoplamento temporal&lt;/strong&gt;: regras que mudam em cadências independentes foram colocadas fisicamente na mesma unidade de código.&lt;/p&gt;

&lt;p&gt;Quando a regra A muda, você é obrigado a abrir, recompilar e reimplantar o mesmo arquivo que executa a regra B — mesmo que B não tenha mudado nada.&lt;/p&gt;

&lt;p&gt;Isso transforma cada alteração pequena em risco grande. E risco grande produz um comportamento defensivo previsível: ninguém quer mexer no método, então as pessoas contornam com condicionais extras em vez de corrigir a estrutura, e o método piora a cada iteração.&lt;/p&gt;

&lt;p&gt;O Strategy ataca exatamente esse acoplamento. Ele separa &lt;strong&gt;o que varia&lt;/strong&gt; do &lt;strong&gt;que permanece estável&lt;/strong&gt;, colocando cada variação em uma classe própria.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conceito: a analogia da fonte de energia
&lt;/h2&gt;

&lt;p&gt;Pense em um notebook e nas tomadas do mundo. O notebook não tem, internamente, uma estrutura condicional perguntando "estou no Brasil? estou no Reino Unido? estou no Japão?" para decidir como converter a energia. Se tivesse, cada país novo exigiria um firmware novo no notebook.&lt;/p&gt;

&lt;p&gt;O que existe é um &lt;strong&gt;contrato&lt;/strong&gt;: a fonte entrega uma tensão estável ao notebook. Como essa tensão foi obtida — de 127V, 220V ou 240V — é problema de quem implementa o contrato, não de quem o consome.&lt;/p&gt;

&lt;p&gt;O Strategy é isso em código:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O &lt;strong&gt;contrato&lt;/strong&gt; é uma interface.&lt;/li&gt;
&lt;li&gt;Cada &lt;strong&gt;variação do algoritmo&lt;/strong&gt; é uma classe que implementa essa interface.&lt;/li&gt;
&lt;li&gt;O &lt;strong&gt;contexto&lt;/strong&gt; (o notebook) conhece apenas a interface, nunca as implementações concretas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A consequência importante: a lógica que decide &lt;em&gt;como&lt;/em&gt; calcular fica isolada da lógica que decide &lt;em&gt;quando&lt;/em&gt; calcular.&lt;/p&gt;




&lt;h2&gt;
  
  
  Estudo de caso: motor de cálculo fiscal em um sistema B2B
&lt;/h2&gt;

&lt;p&gt;Para demonstrar o padrão em um contexto mais próximo dos desafios encontrados em sistemas corporativos, vamos utilizar como exemplo um motor de cálculo fiscal em uma plataforma B2B.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Aviso:&lt;/strong&gt; Os valores, alíquotas e fórmulas apresentados neste artigo são simplificados e possuem finalidade exclusivamente didática. Eles não devem ser utilizados para cálculo tributário real ou tomada de decisão fiscal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  O sistema legado
&lt;/h3&gt;

&lt;p&gt;A plataforma emite notas para clientes de perfis diferentes, e o valor dos tributos depende do &lt;strong&gt;regime tributário&lt;/strong&gt; do cliente: Simples Nacional, Lucro Presumido ou Lucro Real. O código original concentrava tudo em um único método:&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="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="nf"&gt;calcularImpostos&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pedido&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Cliente&lt;/span&gt; &lt;span class="n"&gt;cliente&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;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ZERO&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cliente&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRegime&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SIMPLES"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// faixas de receita, parcela a deduzir, alíquota efetiva&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cliente&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRegime&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PRESUMIDO"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// alíquotas fixas sobre a receita&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cliente&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRegime&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"REAL"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// alíquotas maiores, com desconto de créditos apropriados&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;total&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;h3&gt;
  
  
  Por que isso é um problema de engenharia, e não só código feio
&lt;/h3&gt;

&lt;p&gt;Três características desse domínio tornam o acoplamento caro:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. As regras mudam em datas diferentes e por motivos diferentes.&lt;/strong&gt; Cada regime segue sua própria trilha legislativa. Uma alteração em um não tem relação nenhuma com o outro, mas ambos vivem no mesmo arquivo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Os algoritmos consomem entradas diferentes.&lt;/strong&gt; O Simples precisa da receita bruta acumulada do cliente para descobrir em qual faixa ele está. O Lucro Real precisa dos créditos apropriados no período. O Lucro Presumido não usa nenhum dos dois. Não existe "extrair um método comum" aqui, porque os &lt;em&gt;inputs&lt;/em&gt; divergem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. O raio de explosão de um erro é o faturamento inteiro.&lt;/strong&gt; Uma regressão introduzida ao ajustar a faixa do Simples pode derrubar a emissão de notas dos clientes de Lucro Real, porque compartilham o mesmo caminho de execução.&lt;/p&gt;

&lt;p&gt;Esse é o formato clássico de problema que o Strategy resolve: &lt;strong&gt;variação de algoritmo, com cadência de mudança independente e alto custo de erro.&lt;/strong&gt; A partir daqui, o foco é o padrão; a parte fiscal existe apenas para dar peso realista ao cenário.&lt;/p&gt;

&lt;h3&gt;
  
  
  Escopo do exemplo
&lt;/h3&gt;

&lt;p&gt;Para manter o artigo focado no padrão, as alíquotas e faixas são constantes dentro de cada estratégia. Em um sistema real elas viriam de configuração versionada com data de vigência — uma decisão de infraestrutura ortogonal ao Strategy. Todo o código apresentado abaixo é Java puro e compila sem framework.&lt;/p&gt;




&lt;h2&gt;
  
  
  Representação visual
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Figura 1 — Diagrama UML do Strategy Pattern aplicado ao motor fiscal.&lt;/em&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffmpsfebjytntfw3mq2vy.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffmpsfebjytntfw3mq2vy.png" alt="Diagrama UML de classes: a interface CalculadoraImposto, suas três implementações e a agregação com MotorFiscal" width="799" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O diagrama está restrito às classes que compõem o padrão. &lt;code&gt;Pedido&lt;/code&gt;, &lt;code&gt;Cliente&lt;/code&gt; e as exceções aparecem no código como tipos de apoio, mas incluí-los aqui tiraria o foco da estrutura que importa.&lt;/p&gt;

&lt;p&gt;Repare no losango vazio, indicando agregação, entre &lt;code&gt;MotorFiscal&lt;/code&gt; e &lt;code&gt;CalculadoraImposto&lt;/code&gt;: o motor &lt;strong&gt;usa&lt;/strong&gt; as estratégias, mas não as cria. Esse detalhe é o que separa um Strategy real de um &lt;code&gt;switch&lt;/code&gt; disfarçado.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figura 2 — Arquitetura de alto nível do sistema de cálculo fiscal.&lt;/em&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4q6cmscvloifpm17sjtc.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4q6cmscvloifpm17sjtc.png" alt="Diagrama de arquitetura: o Módulo Fiscal entre a camada de API, o banco de dados e o provedor de NF-e" width="800" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dois pontos que este desenho comunica e o UML não:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A consulta ao banco acontece antes do motor.&lt;/strong&gt; É o dado do cliente que determina qual estratégia será executada — a seleção não é uma decisão tomada em código, é uma consequência de dados que chegam em tempo de execução.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;O Módulo Fiscal é uma fronteira interna, não um serviço remoto.&lt;/strong&gt; O Strategy aqui é uma decisão de organização interna. Ele não introduz nenhuma chamada de rede, e é importante que isso fique visível: padrões de projeto e padrões de arquitetura distribuída resolvem problemas diferentes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Implementação em Java
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tipos de apoio
&lt;/h3&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;enum&lt;/span&gt; &lt;span class="nc"&gt;RegimeTributario&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;SIMPLES_NACIONAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;LUCRO_PRESUMIDO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;LUCRO_REAL&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Cliente&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RegimeTributario&lt;/span&gt; &lt;span class="n"&gt;regimeTributario&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;receitaBruta12Meses&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;uf&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Pedido&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;valorTotal&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;creditosApropriados&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&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;RegimeNaoSuportadoException&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;RegimeNaoSuportadoException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RegimeTributario&lt;/span&gt; &lt;span class="n"&gt;regime&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Nenhuma calculadora registrada para o regime: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;regime&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;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LimiteSimplesExcedidoException&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;LimiteSimplesExcedidoException&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;receita&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Receita acumulada fora das faixas configuradas: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;receita&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;h3&gt;
  
  
  O contrato
&lt;/h3&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="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;ContextoFiscal&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;valorBruto&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;receitaBruta12Meses&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;creditosApropriados&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;uf&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;ContextoFiscal&lt;/span&gt; &lt;span class="nf"&gt;de&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pedido&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Cliente&lt;/span&gt; &lt;span class="n"&gt;cliente&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ContextoFiscal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valorTotal&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                &lt;span class="n"&gt;cliente&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;receitaBruta12Meses&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;creditosApropriados&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                &lt;span class="n"&gt;cliente&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;uf&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;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;ResultadoImposto&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;total&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;RegimeTributario&lt;/span&gt; &lt;span class="n"&gt;regimeAplicado&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;detalhamento&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;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;CalculadoraImposto&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;ResultadoImposto&lt;/span&gt; &lt;span class="nf"&gt;calcular&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ContextoFiscal&lt;/span&gt; &lt;span class="n"&gt;contexto&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nc"&gt;RegimeTributario&lt;/span&gt; &lt;span class="nf"&gt;getRegime&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;O método &lt;code&gt;getRegime()&lt;/code&gt; merece atenção. Ele existe para que &lt;strong&gt;cada estratégia se identifique&lt;/strong&gt;, em vez de alguém externo precisar mapeá-la. É esse detalhe que permite eliminar a estrutura condicional de verdade, em vez de apenas empurrá-la para uma factory.&lt;/p&gt;

&lt;h3&gt;
  
  
  As estratégias
&lt;/h3&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;class&lt;/span&gt; &lt;span class="nc"&gt;SimplesNacionalCalculadora&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;CalculadoraImposto&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Faixa&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;limite&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;aliquotaNominal&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;parcelaDeduzir&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

    &lt;span class="c1"&gt;// Tabela reduzida e simplificada para fins didáticos.&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&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;Faixa&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;FAIXAS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Faixa&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"180000"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;  &lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0.0400"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="o"&gt;)),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Faixa&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"360000"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;  &lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0.0730"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"5940"&lt;/span&gt;&lt;span class="o"&gt;)),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Faixa&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"720000"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;  &lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0.0950"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"13860"&lt;/span&gt;&lt;span class="o"&gt;)),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Faixa&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1800000"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0.1070"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"22500"&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="nc"&gt;ResultadoImposto&lt;/span&gt; &lt;span class="nf"&gt;calcular&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ContextoFiscal&lt;/span&gt; &lt;span class="n"&gt;contexto&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;receita&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contexto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;receitaBruta12Meses&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;Faixa&lt;/span&gt; &lt;span class="n"&gt;faixa&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;FAIXAS&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;f&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;receita&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;limite&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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;orElseThrow&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LimiteSimplesExcedidoException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;receita&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

        &lt;span class="c1"&gt;// Alíquota efetiva = (receita x alíquota nominal - parcela a deduzir) / receita&lt;/span&gt;
        &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;aliquotaEfetiva&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;receita&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;faixa&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;aliquotaNominal&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;subtract&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;faixa&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parcelaDeduzir&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;divide&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;receita&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RoundingMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HALF_UP&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;imposto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contexto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valorBruto&lt;/span&gt;&lt;span class="o"&gt;()&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;aliquotaEfetiva&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setScale&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RoundingMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HALF_UP&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ResultadoImposto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;imposto&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;RegimeTributario&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SIMPLES_NACIONAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IMPOSTO_UNIFICADO"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;imposto&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ALIQUOTA_EFETIVA"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aliquotaEfetiva&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;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;RegimeTributario&lt;/span&gt; &lt;span class="nf"&gt;getRegime&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="nc"&gt;RegimeTributario&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SIMPLES_NACIONAL&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="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="nf"&gt;bd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;valor&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valor&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;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;class&lt;/span&gt; &lt;span class="nc"&gt;LucroPresumidoCalculadora&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;CalculadoraImposto&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Alíquotas ilustrativas.&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="no"&gt;ALIQUOTA_A&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.0065"&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;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="no"&gt;ALIQUOTA_B&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.0300"&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="nc"&gt;ResultadoImposto&lt;/span&gt; &lt;span class="nf"&gt;calcular&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ContextoFiscal&lt;/span&gt; &lt;span class="n"&gt;contexto&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;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contexto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valorBruto&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;tributoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base&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="no"&gt;ALIQUOTA_A&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;setScale&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RoundingMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HALF_UP&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;tributoB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base&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="no"&gt;ALIQUOTA_B&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;setScale&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RoundingMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HALF_UP&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ResultadoImposto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;tributoA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tributoB&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="nc"&gt;RegimeTributario&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LUCRO_PRESUMIDO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TRIBUTO_A"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tributoA&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"TRIBUTO_B"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tributoB&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;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;RegimeTributario&lt;/span&gt; &lt;span class="nf"&gt;getRegime&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="nc"&gt;RegimeTributario&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LUCRO_PRESUMIDO&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;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;class&lt;/span&gt; &lt;span class="nc"&gt;LucroRealCalculadora&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;CalculadoraImposto&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Alíquotas ilustrativas.&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="no"&gt;ALIQUOTA_A&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.0165"&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;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="no"&gt;ALIQUOTA_B&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.0760"&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="nc"&gt;ResultadoImposto&lt;/span&gt; &lt;span class="nf"&gt;calcular&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ContextoFiscal&lt;/span&gt; &lt;span class="n"&gt;contexto&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;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contexto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valorBruto&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;subtract&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contexto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;creditosApropriados&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ZERO&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;tributoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base&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="no"&gt;ALIQUOTA_A&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;setScale&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RoundingMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HALF_UP&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;tributoB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base&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="no"&gt;ALIQUOTA_B&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;setScale&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RoundingMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HALF_UP&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ResultadoImposto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;tributoA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tributoB&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="nc"&gt;RegimeTributario&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LUCRO_REAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TRIBUTO_A"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tributoA&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"TRIBUTO_B"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tributoB&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="s"&gt;"CREDITOS"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contexto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;creditosApropriados&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;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;RegimeTributario&lt;/span&gt; &lt;span class="nf"&gt;getRegime&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="nc"&gt;RegimeTributario&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LUCRO_REAL&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;p&gt;&lt;code&gt;LucroRealCalculadora&lt;/code&gt; usa &lt;code&gt;creditosApropriados&lt;/code&gt; e ignora &lt;code&gt;receitaBruta12Meses&lt;/code&gt;; &lt;code&gt;SimplesNacionalCalculadora&lt;/code&gt; faz o oposto.&lt;/p&gt;

&lt;p&gt;Essa assimetria é a justificativa técnica do padrão: &lt;strong&gt;não são parâmetros diferentes do mesmo algoritmo, são algoritmos diferentes.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  O contexto: onde a condicional desaparece
&lt;/h3&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;class&lt;/span&gt; &lt;span class="nc"&gt;MotorFiscal&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;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RegimeTributario&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;CalculadoraImposto&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;estrategias&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MotorFiscal&lt;/span&gt;&lt;span class="o"&gt;(&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;CalculadoraImposto&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;calculadoras&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;estrategias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculadoras&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;collect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collectors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toUnmodifiableMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                        &lt;span class="nl"&gt;CalculadoraImposto:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getRegime&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;identity&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;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResultadoImposto&lt;/span&gt; &lt;span class="nf"&gt;calcularPara&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pedido&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Cliente&lt;/span&gt; &lt;span class="n"&gt;cliente&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;CalculadoraImposto&lt;/span&gt; &lt;span class="n"&gt;calculadora&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;estrategias&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cliente&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;regimeTributario&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calculadora&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;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RegimeNaoSuportadoException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cliente&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;regimeTributario&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;calculadora&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;calcular&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ContextoFiscal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;de&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cliente&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;p&gt;Este é o coração do artigo. Duas decisões merecem ser explicadas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Collectors.toUnmodifiableMap&lt;/code&gt; falha na inicialização se houver regime duplicado.&lt;/strong&gt; Se alguém criar por engano uma segunda calculadora para &lt;code&gt;LUCRO_REAL&lt;/code&gt;, o coletor lança &lt;code&gt;IllegalStateException&lt;/code&gt; na construção do objeto. Isso é bem melhor do que descobrir em produção que parte das notas usou a implementação errada.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A escolha entre exceção e valor padrão é uma decisão de domínio, não do padrão.&lt;/strong&gt; Aqui a exceção é deliberada: em cálculo tributário, "não sei calcular" precisa interromper a operação, porque um valor padrão silencioso geraria um documento incorreto. Em outros domínios — formatação de texto, política de desconto — um comportamento padrão neutro seria a escolha certa.&lt;/p&gt;

&lt;p&gt;Vale notar que o construtor recebe uma &lt;code&gt;List&lt;/code&gt; justamente para desacoplar o motor de quem monta as estratégias. Em uma aplicação com injeção de dependência, essa lista é preenchida automaticamente; em Java puro, ela é passada na composição da aplicação. O motor não muda em nenhum dos dois casos.&lt;/p&gt;




&lt;h2&gt;
  
  
  O que realmente muda ao adicionar um regime novo
&lt;/h2&gt;

&lt;p&gt;É comum ler que o Strategy permite estender o sistema "sem alterar nenhuma linha de código existente". Na implementação acima, isso não é literalmente verdade, e vale ser preciso.&lt;/p&gt;

&lt;p&gt;Para adicionar um regime novo, é preciso:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Acrescentar uma constante em &lt;code&gt;RegimeTributario&lt;/code&gt; — uma linha, aditiva.&lt;/li&gt;
&lt;li&gt;Criar uma classe nova implementando &lt;code&gt;CalculadoraImposto&lt;/code&gt; e registrá-la na composição da aplicação.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O que &lt;strong&gt;não&lt;/strong&gt; muda:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;MotorFiscal&lt;/code&gt; não é tocado.&lt;/li&gt;
&lt;li&gt;Nenhuma das calculadoras existentes é tocada.&lt;/li&gt;
&lt;li&gt;O código que consome o resultado não é tocado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A diferença em relação ao &lt;code&gt;switch&lt;/code&gt; original é qualitativa, não quantitativa. Lá, você também acrescentaria uma constante — mas depois editaria o mesmo método que executa o cálculo de todos os outros regimes. É essa segunda edição, no código que está em produção e funcionando, que carrega o risco de regressão.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O Strategy não elimina toda alteração; ele elimina a alteração perigosa.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Rigorosamente, o enum ainda é um ponto de extensão que exige modificação, e é justo chamar isso de violação parcial do Princípio Aberto/Fechado. Existe alternativa: usar &lt;code&gt;String&lt;/code&gt; como chave do mapa, lida do banco de dados. Isso removeria até essa linha, ao custo de perder a verificação em tempo de compilação. Manter o enum é um trade-off consciente — em domínio fiscal, um regime escrito errado falhando no &lt;em&gt;build&lt;/em&gt; é preferível a falhar em produção.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testes
&lt;/h2&gt;

&lt;p&gt;Cada estratégia é testável isoladamente, sem instanciar as outras. No método monolítico original, testar um regime exigia carregar todos juntos.&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;class&lt;/span&gt; &lt;span class="nc"&gt;MotorFiscalTest&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;MotorFiscal&lt;/span&gt; &lt;span class="n"&gt;motor&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;MotorFiscal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SimplesNacionalCalculadora&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;LucroPresumidoCalculadora&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;LucroRealCalculadora&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;));&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;deveSelecionarEstrategiaConformeRegimeDoCliente&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cliente&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;Cliente&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RegimeTributario&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LUCRO_PRESUMIDO&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;"500000"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"GO"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pedido&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;Pedido&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;"10000.00"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ZERO&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;ResultadoImposto&lt;/span&gt; &lt;span class="n"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;motor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;calcularPara&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cliente&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultado&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;isEqualByComparingTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"365.00"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultado&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;regimeAplicado&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;isEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RegimeTributario&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LUCRO_PRESUMIDO&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;deveAplicarAliquotaEfetivaNoSimplesNacional&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cliente&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;Cliente&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RegimeTributario&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SIMPLES_NACIONAL&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;"500000"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"GO"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pedido&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;Pedido&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;"10000.00"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ZERO&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;ResultadoImposto&lt;/span&gt; &lt;span class="n"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;motor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;calcularPara&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cliente&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultado&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;isEqualByComparingTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"672.80"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;deveFalharQuandoNaoHaEstrategiaParaORegime&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;MotorFiscal&lt;/span&gt; &lt;span class="n"&gt;motorIncompleto&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;MotorFiscal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&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;LucroPresumidoCalculadora&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cliente&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;Cliente&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RegimeTributario&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LUCRO_REAL&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;"500000"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"GO"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pedido&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;Pedido&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;"10000.00"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ZERO&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;assertThatThrownBy&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;motorIncompleto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;calcularPara&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cliente&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isInstanceOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RegimeNaoSuportadoException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&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;p&gt;O terceiro teste é o mais interessante: ele documenta o comportamento na ausência de estratégia, que é justamente a decisão de domínio discutida acima.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prós e contras
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Vantagens
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extensão com risco contido.&lt;/strong&gt; Adicionar um regime significa uma constante nova e uma classe nova. Nenhum algoritmo existente é editado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Raio de explosão reduzido.&lt;/strong&gt; Uma alteração no cálculo do Simples não pode quebrar o Lucro Real: não compartilham arquivo, estado nem caminho de execução.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testabilidade real.&lt;/strong&gt; Cada algoritmo é uma unidade isolada, com entradas e saídas explícitas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seleção dirigida por dados.&lt;/strong&gt; Como a escolha vem do cadastro do cliente e não de código, fica natural evoluir para cenários como aplicar a regra vigente na data de emissão.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Custos e trade-offs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dispersão da lógica.&lt;/strong&gt; Antes, todas as regras estavam em uma tela; agora estão em vários arquivos. Para quem chega no time, "onde o imposto é calculado?" ficou mais difícil de responder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observabilidade vira requisito.&lt;/strong&gt; Com a condicional, bastava ler o código para saber o que executou. Agora é preciso registrar qual implementação atendeu qual pedido — incluir &lt;code&gt;regimeAplicado&lt;/code&gt; no &lt;code&gt;ResultadoImposto&lt;/code&gt; é resposta direta a esse custo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O objeto de contexto tende a inchar.&lt;/strong&gt; &lt;code&gt;ContextoFiscal&lt;/code&gt; carrega a união dos campos que qualquer estratégia possa precisar, então cada implementação ignora parte deles. É um efeito colateral conhecido do Strategy com contexto compartilhado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mais tipos para manter.&lt;/strong&gt; Cinco classes onde havia um método. Em uma base pequena e estável, isso é cerimônia sem retorno.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;E o trade-off mais importante: se a variação for de dados, Strategy é overengineering.&lt;/strong&gt; Uma alíquota que muda por unidade da federação não merece uma classe por estado — isso é tabela de configuração.&lt;/p&gt;

&lt;p&gt;O sinal prático para distinguir: se as implementações diferem apenas por constantes, você quer uma tabela. Se diferem nos campos que consomem e nos passos que executam, você quer Strategy. Foi esse teste que justificou o padrão aqui.&lt;/p&gt;




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

&lt;p&gt;O Strategy não resolve o problema de "código feio com muitas condicionais". Ele resolve um problema arquitetural mais específico: &lt;strong&gt;regras de negócio que evoluem em ritmos independentes acopladas na mesma unidade de código.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No motor fiscal, o ganho não é estético. É transformar uma alteração de alto risco — mexer no cálculo de todos os clientes para atender à mudança de um regime — em uma alteração isolada e testável. O padrão desloca a modificação para o lugar barato, uma constante em um enum, e a tira do lugar caro, o algoritmo em produção.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visão pessoal
&lt;/h3&gt;

&lt;p&gt;Como estudante e desenvolvedora em formação, minha experiência com Padrões de Projeto até a realização deste estudo era majoritariamente teórica. Ao ler a literatura técnica, a princípio, o Strategy pode parecer apenas uma forma desnecessariamente complexa e verbosa de escrever uma estrutura condicional simples.&lt;/p&gt;

&lt;p&gt;No entanto, o exercício de modelar e implementar este cenário de cálculo tributário mudou completamente minha perspectiva. A verdadeira virada de chave foi ver o Princípio Aberto/Fechado funcionando na prática: a compreensão de que podemos expandir as capacidades de um sistema inteiro apenas adicionando novas classes, sem a necessidade de alterar ou arriscar quebrar o código do motor principal.&lt;/p&gt;

&lt;p&gt;Escrever este artigo também me obrigou a ser mais precisa do que eu esperava. Ao revisar a implementação, percebi que a afirmação comum de que o Strategy dispensa qualquer alteração no código existente não se sustenta inteiramente, já que o enum de regimes ainda precisa receber uma constante nova. Entender por que essa alteração é aceitável — e por que ela é qualitativamente diferente de editar o algoritmo em produção — foi provavelmente o que mais me ensinou no processo.&lt;/p&gt;

&lt;p&gt;Ainda que eu não tenha vivenciado o cenário crítico de manter um sistema legado complexo em produção e lidar com as regressões causadas por um método fortemente acoplado, essa imersão prática cumpriu seu objetivo principal. Ela me forneceu a base arquitetural não apenas para entender como resolver esse tipo de problema, mas, principalmente, para evitar que eu construa sistemas com essas falhas de design no futuro.&lt;/p&gt;

&lt;h3&gt;
  
  
  E você?
&lt;/h3&gt;

&lt;p&gt;Fica a pergunta que mais me interessa: &lt;strong&gt;qual foi a estrutura condicional mais assustadora que você já encontrou em produção — e você refatorou ou concluiu que o risco não valia a pena?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Também quero ouvir discordância: em que situação você acha que manter o &lt;code&gt;switch&lt;/code&gt; foi a decisão certa? Comenta aí.&lt;/p&gt;

</description>
      <category>java</category>
      <category>designpatterns</category>
      <category>architecture</category>
      <category>cleancode</category>
    </item>
  </channel>
</rss>
