<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Padrões De Projeto on Dev On Track!</title><link>https://blog.devontrack.com/pt-br/series/padr%C3%B5es-de-projeto/</link><description>Recent content in Padrões De Projeto on Dev On Track!</description><generator>Hugo -- gohugo.io</generator><language>pt-br</language><lastBuildDate>Sat, 10 Oct 2026 22:28:34 -0300</lastBuildDate><atom:link href="https://blog.devontrack.com/pt-br/series/padr%C3%B5es-de-projeto/index.xml" rel="self" type="application/rss+xml"/><item><title>Padrões de Projeto - Bridge</title><link>https://blog.devontrack.com/pt-br/posts/2023-03-03-design-pattern-bridge/</link><pubDate>Fri, 03 Mar 2023 08:00:00 +0000</pubDate><guid>https://blog.devontrack.com/pt-br/posts/2023-03-03-design-pattern-bridge/</guid><description>&lt;p>&lt;em>&lt;strong>Bridge&lt;/strong>&lt;/em> é um padrão de projeto estrutural que visa desacoplar uma abstração de sua implementação, de forma que permita que ambos evoluam de forma independente.&lt;/p>
&lt;p>O uso desse padrão é recomendado ao lidar com classes que possuem muitas implementações diferentes e usam herança para implementar a abstração. Nesses casos, a herança conecta uma implementação à abstração permanentemente, de forma que é difícil modificar, aumentar e reutilizar as abstrações de forma independente.&lt;/p>
&lt;p>Para dar um exemplo ilustrado, vamos fingir que temos um cenário onde queremos criar diferentes tipos de contas bancárias: &lt;code>CheckingAccount&lt;/code> e &lt;code>SavingsAccount&lt;/code>. Queremos que nosso sistema seja flexível para a criação de novos tipos de contas, então criamos uma classe abstrata chamada &lt;code>BankAccount&lt;/code> e estendemos esta classe com as classes &lt;code>CheckingAccount&lt;/code> e &lt;code>SavingsAccount&lt;/code>.&lt;/p>
&lt;p>Ótimo! Mais tarde, queremos dar aos nossos tipos de conta seu próprio tipo de cartão de crédito personalizado. Criamos as classes &lt;code>BasicCreditCard&lt;/code>, &lt;code>SilverCreditCard&lt;/code> e &lt;code>GoldCreditCard&lt;/code>. Ao vincular esses cartões de crédito a cada tipo de conta bancária, o problema fica claro:&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-03-03/bridge.png"
width="1231"
height="536"
srcset="https://blog.devontrack.com/posts/2023-03-03/bridge_hu_1deed85092858d94.png 480w, https://blog.devontrack.com/posts/2023-03-03/bridge_hu_fab3a7c7328269a9.png 1024w"
loading="lazy"
alt="Implementation without bridge pattern"
class="gallery-image"
data-flex-grow="229"
data-flex-basis="551px"
>&lt;/p>
&lt;p>A abordagem ingênua seria criar uma combinação para cada tipo de conta, uma solução que é cara e cresce exponencialmente (imagine o tanto de trabalho se adicionarmos um novo tipo de conta!). O código também é altamente acoplado, pois estados e comportamentos diferentes estariam contidos em uma única classe.&lt;/p>
&lt;p>O padrão Bridge resolve esse problema mudando de herança para composição e realocando todas as classes &lt;code>CreditCard&lt;/code> para sua própria hierarquia. Ao fazer isso, permitimos que ambos os contextos evoluam e mudem independentemente.&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-03-03/bridge-success.png"
width="1126"
height="486"
srcset="https://blog.devontrack.com/posts/2023-03-03/bridge-success_hu_f0a83ca38cc0d43c.png 480w, https://blog.devontrack.com/posts/2023-03-03/bridge-success_hu_644cdcc413b57b2b.png 1024w"
loading="lazy"
alt="Implementation with bridge pattern"
class="gallery-image"
data-flex-grow="231"
data-flex-basis="556px"
>&lt;/p>
&lt;p>Com esse design em mente, vamos então criar nossa interface &lt;code>CreditCard&lt;/code>:&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-03-03/CreditCard.png"
width="1564"
height="676"
srcset="https://blog.devontrack.com/posts/2023-03-03/CreditCard_hu_d5321153c8a98a5.png 480w, https://blog.devontrack.com/posts/2023-03-03/CreditCard_hu_662469d28ca078cd.png 1024w"
loading="lazy"
alt="CreditCard.java class"
class="gallery-image"
data-flex-grow="231"
data-flex-basis="555px"
>&lt;/p>
&lt;p>Agora, vamos criar nossos tipos: Basic, Silver e Gold, todos implementando os métodos especificados pela interface &lt;code>CreditCard&lt;/code>.&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-03-03/BasicCreditCard.png"
width="1840"
height="1756"
srcset="https://blog.devontrack.com/posts/2023-03-03/BasicCreditCard_hu_b42616b3ef80b28d.png 480w, https://blog.devontrack.com/posts/2023-03-03/BasicCreditCard_hu_ed51e76969a7f099.png 1024w"
loading="lazy"
alt="BasicCreditCard.java class"
class="gallery-image"
data-flex-grow="104"
data-flex-basis="251px"
>&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-03-03/SilverCreditCard.png"
width="1840"
height="1710"
srcset="https://blog.devontrack.com/posts/2023-03-03/SilverCreditCard_hu_bf63812951305d27.png 480w, https://blog.devontrack.com/posts/2023-03-03/SilverCreditCard_hu_4311d3bc9e7bd146.png 1024w"
loading="lazy"
alt="SilverCreditCard.java class"
class="gallery-image"
data-flex-grow="107"
data-flex-basis="258px"
>&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-03-03/GoldCreditCard.png"
width="1840"
height="1756"
srcset="https://blog.devontrack.com/posts/2023-03-03/GoldCreditCard_hu_ddc5195eb59514de.png 480w, https://blog.devontrack.com/posts/2023-03-03/GoldCreditCard_hu_3a910a8a5d5d03b2.png 1024w"
loading="lazy"
alt="GoldCreditCard.java class"
class="gallery-image"
data-flex-grow="104"
data-flex-basis="251px"
>&lt;/p>
&lt;p>Vamos criar a abstração &lt;code>BankAccount&lt;/code>, a classe base para nossos tipos de conta. Esta classe terá um objeto &lt;code>CreditCard&lt;/code>, bem como um método para obter as informações do cartão.&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-03-03/BankAccount.png"
width="1174"
height="720"
srcset="https://blog.devontrack.com/posts/2023-03-03/BankAccount_hu_bbc15e4578a91e13.png 480w, https://blog.devontrack.com/posts/2023-03-03/BankAccount_hu_e531f164e851551.png 1024w"
loading="lazy"
alt="BankAccount.java class"
class="gallery-image"
data-flex-grow="163"
data-flex-basis="391px"
>&lt;/p>
&lt;p>Com tudo criado, podemos escrever nossos tipos de conta &lt;code>CheckingAccount&lt;/code> e &lt;code>SavingsAccount&lt;/code>:&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-03-03/CheckingAccount.png"
width="1802"
height="1016"
srcset="https://blog.devontrack.com/posts/2023-03-03/CheckingAccount_hu_f8dce44562d45a3b.png 480w, https://blog.devontrack.com/posts/2023-03-03/CheckingAccount_hu_c00d1f2b61b9de9a.png 1024w"
loading="lazy"
alt="CheckingAccount.java class"
class="gallery-image"
data-flex-grow="177"
data-flex-basis="425px"
>&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-03-03/SavingsAccount.png"
width="1784"
height="972"
srcset="https://blog.devontrack.com/posts/2023-03-03/SavingsAccount_hu_cf1c78deecfc2d17.png 480w, https://blog.devontrack.com/posts/2023-03-03/SavingsAccount_hu_adef77b32cb748bc.png 1024w"
loading="lazy"
alt="SavingsAccount.java class"
class="gallery-image"
data-flex-grow="183"
data-flex-basis="440px"
>&lt;/p>
&lt;p>Para testar nosso projeto, criaremos uma classe principal inicializando cada conta com seus respectivos tipos de cartão de crédito.&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-03-03/BridgeApplication.png"
width="1840"
height="972"
srcset="https://blog.devontrack.com/posts/2023-03-03/BridgeApplication_hu_dc25a90c10b224a9.png 480w, https://blog.devontrack.com/posts/2023-03-03/BridgeApplication_hu_27096a6468bf459d.png 1024w"
loading="lazy"
alt="BridgeApplication.java class"
class="gallery-image"
data-flex-grow="189"
data-flex-basis="454px"
>&lt;/p>
&lt;p>&amp;hellip;que gera o seguinte conteúdo:&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-03-03/Output.png"
width="2594"
height="1212"
srcset="https://blog.devontrack.com/posts/2023-03-03/Output_hu_836e3352a8446eab.png 480w, https://blog.devontrack.com/posts/2023-03-03/Output_hu_5703c3f88097633b.png 1024w"
loading="lazy"
alt="Output.java class"
class="gallery-image"
data-flex-grow="214"
data-flex-basis="513px"
>&lt;/p>
&lt;p>No fim das contas, o padrão Bridge é uma ótima ferramenta para ser utilizada quando queremos dividir e refatorar classes com muitas variantes, e também quando precisamos estender uma classe em dimensões independentes. Um grande benefício em usar esse padrão é que ele segue o &lt;strong>princípio aberto/fechado&lt;/strong> (já que podemos adicionar abstrações e implementações sem afetar as existentes) e o &lt;strong>princípio de responsabilidade única&lt;/strong>.&lt;/p>
&lt;p>Você pode verificar a implementação completa deste exemplo &lt;a class="link" href="https://github.com/GracieleDamasceno/design-patterns" target="_blank" rel="noopener"
>aqui no meu Github: GracieleDamasceno/design-patterns&lt;/a>!&lt;/p>
&lt;h4 id="referências">&lt;a href="#refer%c3%aancias" class="header-anchor">&lt;/a>Referências:
&lt;/h4>&lt;p>&lt;a class="link" href="https://refactoring.guru/design-patterns/bridge" target="_blank" rel="noopener"
>Bridge Pattern - Refactoring Guru&lt;/a>&lt;/p>
&lt;p>&lt;a class="link" href="https://www.google.com.br/books/edition/Valuepack_Design_Patterns_Elements_of_Re/VDRePgAACAAJ" target="_blank" rel="noopener"
>Design Patterns&lt;/a> (2005), By &lt;a class="link" href="https://www.google.com.br/search?hl=pt-BR&amp;amp;q=inauthor:%22Erich&amp;#43;Gamma%22&amp;amp;tbm=bks" target="_blank" rel="noopener"
>Erich Gamma&lt;/a>, &lt;a class="link" href="https://www.google.com.br/search?hl=pt-BR&amp;amp;q=inauthor:%22Richard&amp;#43;Helm%22&amp;amp;tbm=bks" target="_blank" rel="noopener"
>Richard Helm&lt;/a>, &lt;a class="link" href="https://www.google.com.br/search?hl=pt-BR&amp;amp;q=inauthor:%22Ralph&amp;#43;Johnson%22&amp;amp;tbm=bks" target="_blank" rel="noopener"
>Ralph Johnson&lt;/a>, &lt;a class="link" href="https://www.google.com.br/search?hl=pt-BR&amp;amp;q=inauthor:%22John&amp;#43;Vlissides%22&amp;amp;tbm=bks" target="_blank" rel="noopener"
>John Vlissides&lt;/a>, &lt;a class="link" href="https://www.google.com.br/search?hl=pt-BR&amp;amp;q=inauthor:%22Craig&amp;#43;Larman%22&amp;amp;tbm=bks" target="_blank" rel="noopener"
>Craig Larman&lt;/a>&lt;/p></description></item><item><title>Padrões de Projeto - Adapter</title><link>https://blog.devontrack.com/pt-br/posts/2023-02-18-design-pattern-adapter/</link><pubDate>Sat, 18 Feb 2023 08:00:00 +0000</pubDate><guid>https://blog.devontrack.com/pt-br/posts/2023-02-18-design-pattern-adapter/</guid><description>&lt;p>&lt;em>&lt;strong>Adapter&lt;/strong>&lt;/em> é um padrão de projeto com a finalidade de - como o próprio nome sugere - adaptar um contexto à outro, permitindo que duas interfaces incompatíveis sejam conectadas. O principal benefício de aplicar esse padrão é permitir trocar de uma interface existente para outra sem alterar o comportamento original da interface existente. o Adapter também é usado quando há a necessidade de criar uma classe reutilizável que interaja com interfaces incompatíveis. Vamos ver esse padrão em ação!&lt;/p>
&lt;h2 id="adaptando-a-saída-existente-para-uma-nova">&lt;a href="#adaptando-a-sa%c3%adda-existente-para-uma-nova" class="header-anchor">&lt;/a>Adaptando a saída existente para uma nova
&lt;/h2>&lt;p>Em nosso cenário, temos uma POJO de pessoa que contém alguns atributos.&lt;/p>
&lt;br>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-02-18/Person.png"
width="1040"
height="1016"
srcset="https://blog.devontrack.com/posts/2023-02-18/Person_hu_2a6a8e610182fe12.png 480w, https://blog.devontrack.com/posts/2023-02-18/Person_hu_468b9fad6e3b597c.png 1024w"
loading="lazy"
alt="Person.java"
class="gallery-image"
data-flex-grow="102"
data-flex-basis="245px"
>&lt;/p>
&lt;br>
&lt;p>Existe também uma interface que dita qual será o contrato de negócio do objeto Pessoa. Em nosso caso, o contrato existente estabelece que a resposta da classe &lt;code>Person&lt;/code> deve ser uma string formatada em XML.&lt;/p>
&lt;br>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-02-18/PersonOutput.png"
width="1040"
height="342"
srcset="https://blog.devontrack.com/posts/2023-02-18/PersonOutput_hu_3fbaab79c1ac57a4.png 480w, https://blog.devontrack.com/posts/2023-02-18/PersonOutput_hu_903d318d5ee261b3.png 1024w"
loading="lazy"
alt="PersonOutput.java"
class="gallery-image"
data-flex-grow="304"
data-flex-basis="729px"
>&lt;/p>
&lt;p>&lt;br>E a classe &lt;code>LegacyPersonService&lt;/code> implementa esse contrato, construindo um objeto da classe &lt;code>Person&lt;/code> e retornando-o em string, formatada em XML.&lt;/p>
&lt;br>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-02-18/LegacyPersonService.png"
width="1658"
height="1466"
srcset="https://blog.devontrack.com/posts/2023-02-18/LegacyPersonService_hu_bc13637398cb571e.png 480w, https://blog.devontrack.com/posts/2023-02-18/LegacyPersonService_hu_fe431d41aaa599ec.png 1024w"
loading="lazy"
alt="LegacyPersonService.java"
class="gallery-image"
data-flex-grow="113"
data-flex-basis="271px"
>&lt;/p>
&lt;br>
&lt;p>Essa arquitetura funciona bem por um bom tempo, até que seja necessário redesenhar nosso sistema. Como nesse cenário temos muitas dependências externas e cruciais, a resposta em XML tem que coexistir com a nova solução, que tem como objetivo ter a resposta em string no formato JSON.&lt;/p>
&lt;p>É exatamente aí que o padrão do adaptador é muito útil!&lt;/p>
&lt;p>Vamos adaptar nossa solução anterior para gerar um JSON, seguindo os novos requisitos. Primeiro, vamos implementar uma interface que dite esse novo contrato.&lt;/p>
&lt;br>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-02-18/PersonOutputAdapter.png"
width="1040"
height="386"
srcset="https://blog.devontrack.com/posts/2023-02-18/PersonOutputAdapter_hu_7e48ac8c1b4e2ac9.png 480w, https://blog.devontrack.com/posts/2023-02-18/PersonOutputAdapter_hu_4fae8e419e527c35.png 1024w"
loading="lazy"
alt="PersonOutputAdapter.java"
class="gallery-image"
data-flex-grow="269"
data-flex-basis="646px"
>&lt;/p>
&lt;p>&lt;br>Agora, criamos o adapter: implementando a interface criada anteriormente, instanciamos a classe &lt;code>LegacyPersonService&lt;/code> que contém a lógica do contrato antigo e implementamos a nova lógica para transformar a resposta em uma string em JSON.
&lt;br>&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-02-18/ModernizedPersonAdapter.png"
width="1420"
height="836"
srcset="https://blog.devontrack.com/posts/2023-02-18/ModernizedPersonAdapter_hu_a6bf557d114917ad.png 480w, https://blog.devontrack.com/posts/2023-02-18/ModernizedPersonAdapter_hu_50b990aca4be17b7.png 1024w"
loading="lazy"
alt="ModernizedPersonAdapter.java"
class="gallery-image"
data-flex-grow="169"
data-flex-basis="407px"
>
&lt;br>&lt;/p>
&lt;p>Com a lógica criada, podemos criar tranquilamente uma nova versão do nosso endpoint que atenda à nova especificação, sem alterar a que já existia.&lt;/p>
&lt;br>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2023-02-18/PersonController.png"
width="1840"
height="1286"
srcset="https://blog.devontrack.com/posts/2023-02-18/PersonController_hu_b2a78282c0f1ac84.png 480w, https://blog.devontrack.com/posts/2023-02-18/PersonController_hu_a98c70c1e2a8f098.png 1024w"
loading="lazy"
alt="PersonController.java"
class="gallery-image"
data-flex-grow="143"
data-flex-basis="343px"
>&lt;/p>
&lt;br>
&lt;p>Então, para resumir:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>O padrão de Adapter segue o &lt;strong>princípio aberto-fechado&lt;/strong>. Podemos adicionar novos adaptadores sem alterar o código existente.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>O padrão de Adapter também segue o princípio da &lt;strong>responsabilidade única&lt;/strong>, pois separamos a interface/contrato da lógica de negócios existente.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>No nosso caso, foi utilizada composição na classe &lt;code>ModernizedPersonAdapter&lt;/code> para encapsular o alvo do adaptador (&lt;code>LegacyPersonService&lt;/code>). Esta forma de lidar com a classe &lt;em>adaptada&lt;/em> é chamada de &lt;strong>Object Adapter&lt;/strong>.&lt;/p>
&lt;ul>
&lt;li>A outra forma de implementar um adaptador seria usando o estilo &lt;strong>Class Adapter&lt;/strong>, onde ao invés de criar um objeto &lt;code>LegacyPersonService&lt;/code> em &lt;code>ModernizedPersonAdapter&lt;/code>, estenderíamos &lt;code>LegacyPersonService&lt;/code> e implementaríamos &lt;code>PersonOutputAdapter&lt;/code> simultaneamente. Ambas são abordagens válidas, no entanto, é melhor favorecer a composição em detrimento da herança, pois permite que o sistema seja mais fácil de testar, menos complexo e desacoplado.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>A principal desvantagem que esse padrão oferece é o aumento da complexidade ao adicionar novos componentes à aplicação. Dependendo da situação e das restrições externas, é melhor apenas refatorar o código existente para corresponder ao novo contrato.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;br>
&lt;p>Você pode dar uma olhada no código &lt;a class="link" href="https://github.com/GracieleDamasceno/design-patterns" target="_blank" rel="noopener"
>aqui no meu Github: GracieleDamasceno/design-patterns&lt;/a>! Até a próxima!&lt;/p>
&lt;br>
&lt;h2 id="referências">&lt;a href="#refer%c3%aancias" class="header-anchor">&lt;/a>Referências:
&lt;/h2>&lt;p>&lt;a class="link" href="https://en.wikipedia.org/wiki/Composition_over_inheritance" target="_blank" rel="noopener"
>Composition over inheritance - Wikipedia&lt;/a>&lt;/p>
&lt;p>&lt;a class="link" href="https://refactoring.guru/design-patterns/adapter" target="_blank" rel="noopener"
>Adapter Pattern - Refactoring Guru&lt;/a>&lt;/p></description></item><item><title>Padrões de Projeto - Prototype</title><link>https://blog.devontrack.com/pt-br/posts/2022-11-04-design-pattern-prototype/</link><pubDate>Fri, 04 Nov 2022 08:00:00 +0000</pubDate><guid>https://blog.devontrack.com/pt-br/posts/2022-11-04-design-pattern-prototype/</guid><description>&lt;p>Continuando nossa série de padrões de projeto, o segundo que iremos revisitar é o Prototype!&lt;/p>
&lt;p>Este padrão visa ter um “planta” para gerar instâncias. Isso é muito útil em situações onde existem vários objetos com propriedades diferentes, onde seja custoso criar novos recursos e quando queremos especificar a instanciação da classe em tempo de execução.&lt;/p>
&lt;p>Basicamente, para implementar um Prototype, temos que adicionar à classe original desejada um método que clona uma instância baseada na original. O próximo passo é criar uma espécie de “registro” que mantenha um cache dos objetos prototipados; seguido por uma classe de fábrica que clona o original e retorna o resultado.&lt;/p>
&lt;p>O processo de clonagem é um dos aspecto mais importantes do Prototype, então, para entender melhor as nuances escondidas na clonagem de um objeto, vamos falar sobre Deep Cloning e Shallow Cloning.&lt;/p>
&lt;h2 id="deep-cloning-versus-shallow-cloning">&lt;a href="#deep-cloning-versus-shallow-cloning" class="header-anchor">&lt;/a>Deep Cloning versus Shallow Cloning
&lt;/h2>&lt;p>&lt;strong>Deep Cloning&lt;/strong> significa que, ao clonar, cada cópia terá sua própria referência. Se alterarmos um atributo da cópia, o original permanecerá intacto.&lt;/p>
&lt;p>O mesmo não acontece com o &lt;strong>Shallow Cloning:&lt;/strong> tanto a cópia quanto o original compartilham a mesma referência. Isso significa que as alterações feitas nos atributos de cópia também serão refletidas nos atributos do objeto original.&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2022-11-04/diagram-shallow-deep-cloning.png"
width="1217"
height="508"
srcset="https://blog.devontrack.com/posts/2022-11-04/diagram-shallow-deep-cloning_hu_eacc1f1d62668ffd.png 480w, https://blog.devontrack.com/posts/2022-11-04/diagram-shallow-deep-cloning_hu_9ab545d7486f9ce2.png 1024w"
loading="lazy"
alt="Deep Cloning vs Shallow Cloning"
class="gallery-image"
data-flex-grow="239"
data-flex-basis="574px"
>&lt;/p>
&lt;h2 id="implementando-o-padrão-prototype-em-java">&lt;a href="#implementando-o-padr%c3%a3o-prototype-em-java" class="header-anchor">&lt;/a>Implementando o Padrão Prototype em Java
&lt;/h2>&lt;p>Existem algumas “&lt;em>pegadinhas&lt;/em>” ao implementar o Prototype em Java: A escolha óbvia, a interface &lt;code>Cloneable&lt;/code> do Java, é comumente conhecida por ser defeituosa. Simplesmente não existe um mecanismo construído em Java para criar &amp;ldquo;deep clones&amp;rdquo; nativamente, o que significa que implementar &lt;code>Cloneable&lt;/code> e chamar &lt;code>super.clone()&lt;/code> sempre criará uma cópia superficial. Pior ainda, a interface &lt;code>Cloneable&lt;/code> é uma classe &lt;em>marker&lt;/em> que apenas marca a classe que a implementa como adequada para clonagem, e não possui um método &lt;code>clone()&lt;/code> próprio (este método existe na classe Object).&lt;/p>
&lt;p>Esses fatores argumentam por ser uma escolha melhor usar cópia via construtores para criar clones ao invés do &lt;code>Cloneable&lt;/code> do Java.&lt;/p>
&lt;p>Com isso em mente, vamos tentar usar o Prototype para resolver um problema. O conceito é o seguinte: Queremos acompanhar algumas Criptomoedas que foram compradas em 1º de janeiro de 2022. Os valores nesse período preenchem a instância original quando o aplicativo é iniciado. O usuário envia sua escolha de criptomoeda e o aplicativo chama um endpoint para obter informações em tempo real sobre essa criptomoeda específica, calcula a diferença entre o antes e o depois e envia de volta em um relatório.&lt;/p>
&lt;p>Esse é o diagrama de arquitetura do aplicativo:&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2022-11-04/diagram-prototype.png"
width="1566"
height="891"
srcset="https://blog.devontrack.com/posts/2022-11-04/diagram-prototype_hu_1ac7681f8a2e6e16.png 480w, https://blog.devontrack.com/posts/2022-11-04/diagram-prototype_hu_c1364acfac621279.png 1024w"
loading="lazy"
alt="Prototype Architecture"
class="gallery-image"
data-flex-grow="175"
data-flex-basis="421px"
>&lt;/p>
&lt;p>A classe de controller da aplicação é a seguinte:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@RestController&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@AllArgsConstructor&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CryprocurrencyController&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">final&lt;/span> CryptocurrencyService cryptocurrencyService;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@GetMapping&lt;/span>(value &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;/crypto/{cryptocurrencyType}&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> CryptocurrencyReport &lt;span style="color:#a6e22e">cryptocurrencyController&lt;/span>(&lt;span style="color:#a6e22e">@PathVariable&lt;/span> CryptocurrencyTypeEnum cryptocurrencyType) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> cryptocurrencyService.&lt;span style="color:#a6e22e">getCryptocurrencyReport&lt;/span>(cryptocurrencyType);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Então, o controller invoca a service:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@Service&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@AllArgsConstructor&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CryptocurrencyService&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">final&lt;/span> CryptocurrencyClient cryptocurrencyClient;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">final&lt;/span> CryptocurrencyLoader cryptocurrencyLoader;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> CryptocurrencyReport &lt;span style="color:#a6e22e">getCryptocurrencyReport&lt;/span>(CryptocurrencyTypeEnum cryptocurrencyTypeEnum){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//Get original Cryptocurrency instance&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Cryptocurrency cryptocurrencyAtPurchase &lt;span style="color:#f92672">=&lt;/span> cryptocurrencyLoader.&lt;span style="color:#a6e22e">getCryptocurrencyLoaded&lt;/span>(cryptocurrencyTypeEnum);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//Get Cryptocurrency cloned with updated values&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Cryptocurrency cryptocurrencyNow &lt;span style="color:#f92672">=&lt;/span> getUpdatedCryptocurrencyValues(cryptocurrencyTypeEnum);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//Returns the report calculating variation between purshased value and current value&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> CryptocurrencyReport.&lt;span style="color:#a6e22e">builder&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">cryptocurrencyCurrentValues&lt;/span>(cryptocurrencyNow)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">cryptocurrencyPurchaseValues&lt;/span>(cryptocurrencyAtPurchase)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">rankVariation&lt;/span>(calculateVariation(cryptocurrencyAtPurchase.&lt;span style="color:#a6e22e">getRank&lt;/span>(), cryptocurrencyNow.&lt;span style="color:#a6e22e">getRank&lt;/span>()))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">priceUSDVariation&lt;/span>(calculateVariation(cryptocurrencyAtPurchase.&lt;span style="color:#a6e22e">getPriceUSD&lt;/span>(), cryptocurrencyNow.&lt;span style="color:#a6e22e">getPriceUSD&lt;/span>()))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">volume24Variation&lt;/span>(calculateVariation(cryptocurrencyAtPurchase.&lt;span style="color:#a6e22e">getVolume24&lt;/span>(), cryptocurrencyNow.&lt;span style="color:#a6e22e">getVolume24&lt;/span>()))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">marketCapUSDVariation&lt;/span>(calculateVariation(cryptocurrencyAtPurchase.&lt;span style="color:#a6e22e">getMarketCapUSD&lt;/span>(), cryptocurrencyNow.&lt;span style="color:#a6e22e">getMarketCapUSD&lt;/span>()))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">build&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> Cryptocurrency &lt;span style="color:#a6e22e">getUpdatedCryptocurrencyValues&lt;/span>(CryptocurrencyTypeEnum cryptocurrencyTypeEnum){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//Requests current Crypto&amp;#39;s data &lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">final&lt;/span> CryptocurrencyDTO cryptocurrencyDTO &lt;span style="color:#f92672">=&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrencyClient.&lt;span style="color:#a6e22e">getCryptocurrency&lt;/span>(cryptocurrencyTypeEnum.&lt;span style="color:#a6e22e">getId&lt;/span>()).&lt;span style="color:#a6e22e">iterator&lt;/span>().&lt;span style="color:#a6e22e">next&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//Loads original cripto values&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Cryptocurrency cryptocurrencyLoaded &lt;span style="color:#f92672">=&lt;/span> cryptocurrencyLoader.&lt;span style="color:#a6e22e">getCryptocurrencyLoaded&lt;/span>(cryptocurrencyTypeEnum);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//Maps the current values to the original Criptocurrency object&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> updateLoadedPrototypeWithCurrentValues(cryptocurrencyDTO, cryptocurrencyLoaded);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> BigDecimal &lt;span style="color:#a6e22e">calculateVariation&lt;/span>(BigDecimal valueBefore, BigDecimal valueNow){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> valueNow.&lt;span style="color:#a6e22e">subtract&lt;/span>(valueBefore);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> Integer &lt;span style="color:#a6e22e">calculateVariation&lt;/span>(Integer valueBefore, Integer valueNow){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> valueNow &lt;span style="color:#f92672">-&lt;/span> valueBefore;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Essa é a classe que realiza o mapeamento do objeto recebido para o clone:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@NoArgsConstructor&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CryptocurrencyDTOMapper&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">static&lt;/span> Cryptocurrency &lt;span style="color:#a6e22e">updateLoadedPrototypeWithCurrentValues&lt;/span>(CryptocurrencyDTO cryptocurrencyDTO, Cryptocurrency cryptocurrencyLoaded){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrencyLoaded.&lt;span style="color:#a6e22e">setRank&lt;/span>(cryptocurrencyDTO.&lt;span style="color:#a6e22e">getRank&lt;/span>());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrencyLoaded.&lt;span style="color:#a6e22e">setPriceUSD&lt;/span>(cryptocurrencyDTO.&lt;span style="color:#a6e22e">getPriceUSD&lt;/span>());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrencyLoaded.&lt;span style="color:#a6e22e">setVolume24&lt;/span>(cryptocurrencyDTO.&lt;span style="color:#a6e22e">getVolume24&lt;/span>());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrencyLoaded.&lt;span style="color:#a6e22e">setMarketCapUSD&lt;/span>(cryptocurrencyDTO.&lt;span style="color:#a6e22e">getMarketCapUSD&lt;/span>());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> cryptocurrencyLoaded;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>A classe que carrega a instância de Cryptocurrency:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@Component&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CryptocurrencyLoader&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> HashMap&lt;span style="color:#f92672">&amp;lt;&lt;/span>String, Cryptocurrency&lt;span style="color:#f92672">&amp;gt;&lt;/span> cryptocurrencyTable &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> HashMap&lt;span style="color:#f92672">&amp;lt;&amp;gt;&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//Returns crypto object based on the enum requested by the user&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> Cryptocurrency &lt;span style="color:#a6e22e">getCryptocurrencyLoaded&lt;/span>(CryptocurrencyTypeEnum crypto){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Cryptocurrency loadedCryptocurrency &lt;span style="color:#f92672">=&lt;/span> cryptocurrencyTable.&lt;span style="color:#a6e22e">get&lt;/span>(crypto.&lt;span style="color:#a6e22e">getId&lt;/span>());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//Here the cloning happens!&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Cryptocurrency(loadedCryptocurrency);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//Loads the crypto information on application startup&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@PostConstruct&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">loadCryptoInfo1stJanuary2022&lt;/span>(){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Cryptocurrency bitcoin &lt;span style="color:#f92672">=&lt;/span> Cryptocurrency.&lt;span style="color:#a6e22e">builder&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">id&lt;/span>(CryptocurrencyTypeEnum.&lt;span style="color:#a6e22e">BTC&lt;/span>.&lt;span style="color:#a6e22e">getId&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">name&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;BITCOIN&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">symbol&lt;/span>(CryptocurrencyTypeEnum.&lt;span style="color:#a6e22e">BTC&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">rank&lt;/span>(1)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">volume24&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> BigDecimal(&lt;span style="color:#e6db74">&amp;#34;24582667004&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">priceUSD&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> BigDecimal(&lt;span style="color:#e6db74">&amp;#34;47686.81&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">marketCapUSD&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> BigDecimal(&lt;span style="color:#e6db74">&amp;#34;902104193385&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">build&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Cryptocurrency ethereum &lt;span style="color:#f92672">=&lt;/span> Cryptocurrency.&lt;span style="color:#a6e22e">builder&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">id&lt;/span>(CryptocurrencyTypeEnum.&lt;span style="color:#a6e22e">ETH&lt;/span>.&lt;span style="color:#a6e22e">getId&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">name&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;ETHEREUM&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">symbol&lt;/span>(CryptocurrencyTypeEnum.&lt;span style="color:#a6e22e">ETH&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">rank&lt;/span>(1)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">volume24&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> BigDecimal(&lt;span style="color:#e6db74">&amp;#34;9776191466&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">priceUSD&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> BigDecimal(&lt;span style="color:#e6db74">&amp;#34;3769.70&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">marketCapUSD&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> BigDecimal(&lt;span style="color:#e6db74">&amp;#34;448537615143&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">build&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrencyTable.&lt;span style="color:#a6e22e">put&lt;/span>(CryptocurrencyTypeEnum.&lt;span style="color:#a6e22e">BTC&lt;/span>.&lt;span style="color:#a6e22e">getId&lt;/span>(), bitcoin);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrencyTable.&lt;span style="color:#a6e22e">put&lt;/span>(CryptocurrencyTypeEnum.&lt;span style="color:#a6e22e">ETH&lt;/span>.&lt;span style="color:#a6e22e">getId&lt;/span>(), ethereum);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Finalmente, a classe de Cryptocurrency que realiza a clonagem através do construtor com um parâmetro:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@Getter&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@Setter&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@Builder&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@NoArgsConstructor&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@AllArgsConstructor&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Cryptocurrency&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> String id;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> CryptocurrencyTypeEnum symbol;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> String name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> Integer rank;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@JsonProperty&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;price_usd&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> BigDecimal priceUSD;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@JsonProperty&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;volume_24&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> BigDecimal volume24;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@JsonProperty&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;market_cap_usd&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> BigDecimal marketCapUSD;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"> * Since the clone method from Cloneable class is broken, we use a copy constructor.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"> * */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">Cryptocurrency&lt;/span>(Cryptocurrency cryptocurrency) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">this&lt;/span>(cryptocurrency.&lt;span style="color:#a6e22e">getId&lt;/span>(),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrency.&lt;span style="color:#a6e22e">getSymbol&lt;/span>(),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrency.&lt;span style="color:#a6e22e">getName&lt;/span>(),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrency.&lt;span style="color:#a6e22e">getRank&lt;/span>(),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrency.&lt;span style="color:#a6e22e">getPriceUSD&lt;/span>(),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrency.&lt;span style="color:#a6e22e">getVolume24&lt;/span>(),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cryptocurrency.&lt;span style="color:#a6e22e">getMarketCapUSD&lt;/span>());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Você pode checar a implementação completa do projeto &lt;a class="link" href="https://github.com/GracieleDamasceno/design-patterns/tree/main/prototype" target="_blank" rel="noopener"
>clicando aqui.&lt;/a>&lt;/p>
&lt;h2 id="referências">&lt;a href="#refer%c3%aancias" class="header-anchor">&lt;/a>Referências
&lt;/h2>&lt;p>Discussões interessantes sobre o Cloneable do Java:&lt;/p>
&lt;p>&lt;a class="link" href="https://programming.guide/java/clone-and-cloneable.html" target="_blank" rel="noopener"
>Java: Clone and Cloneable &amp;gt; Programming.Guide&lt;/a>&lt;/p>
&lt;p>&lt;a class="link" href="https://www.vojtechruzicka.com/java-cloning-problems/" target="_blank" rel="noopener"
>Java Cloning Problems &amp;gt; Vojtech Ruzicka&amp;rsquo;s Programming Blog&lt;/a>&lt;/p>
&lt;p>&lt;a class="link" href="http://www.javapractices.com/topic/TopicAction.do?Id=12" target="_blank" rel="noopener"
>Copy constructors &amp;gt; Java Practices&lt;/a>&lt;/p></description></item><item><title>Padrões de Projeto - Factory</title><link>https://blog.devontrack.com/pt-br/posts/2022-08-29-design-pattern-factory/</link><pubDate>Mon, 29 Aug 2022 08:00:00 +0000</pubDate><guid>https://blog.devontrack.com/pt-br/posts/2022-08-29-design-pattern-factory/</guid><description>&lt;p>Hoje vamos dar uma olhada no Padrão de Projeto &amp;ldquo;Factory&amp;rdquo;.&lt;/p>
&lt;p>Imagine que você tenha que construir uma applicação que envie uma mensagem especificada pelo usuário usando diferentes métodos de entrega. Por exemplo, o usuário poderia enviar sua mensagem usando SMS, uma notificação push para um celular, e-mail&amp;hellip;&lt;/p>
&lt;p>Seria um incômodo construir muitas classes diferentes para receber a mensagem do usuário e entregá-la! Quero dizer, imagine se o usuário tiver que utilizar diferentes endpoints/argumentos para enviar cada tipo de mensagem. Pensando em código, teríamos que criar um método que chamasse cada uma das classes que enviariam uma mensagem de cada maneira específica. Mas e se eu quiser desenvolver outro tipo de método de entrega? Eu teria que alterar a lógica que envia cada mensagem para seu respectivo tipo e, se não tomar cuidado, poderia excluir ou modificar partes importantes dessa lógica. Meu código teria muitas condições e poderia ser altamente acoplado.&lt;/p>
&lt;p>Os Padrões de Projeto sugerem uma maneira bem legal de resolver esse problema. Vamos ver como!&lt;/p>
&lt;h3 id="mãos-a-obra">&lt;a href="#m%c3%a3os-a-obra" class="header-anchor">&lt;/a>Mãos a obra!
&lt;/h3>&lt;p>Primeiro, vamos dar uma olhadinha no nosso diagrama de arquitetura.&lt;/p>
&lt;p>&lt;img src="https://blog.devontrack.com/posts/2022-08-29/factory-diagram.png"
width="1521"
height="851"
srcset="https://blog.devontrack.com/posts/2022-08-29/factory-diagram_hu_4f2ad58a013a3a08.png 480w, https://blog.devontrack.com/posts/2022-08-29/factory-diagram_hu_6be78175bed7bd.png 1024w"
loading="lazy"
alt="Notification Factory Diagram"
class="gallery-image"
data-flex-grow="178"
data-flex-basis="428px"
>&lt;/p>
&lt;p>A ideia principal é criar uma interface de notificação que terá um método de entrega definido, para que cada uma das classes implemente suas próprias especificidades da entrega. Há cinco métodos de entrega definidos, e esses métodos serão chamados com base em um parâmetro enviado pelo usuário por meio de uma classe de service. Daqui a pouco vamos ver mais detalhes sobre isso.&lt;/p>
&lt;p>Esse projeto usa Java com Spring, e uma chamada &lt;code>REST&lt;/code> para receber a mensagem desejada. Vamos começar criando um controller &lt;code>REST&lt;/code> onde o usuário pode postar sua mensagem e o tipo de entrega selecionado.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@Slf4j&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@RestController&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@AllArgsConstructor&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">NotificationController&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> NotificationService notificationService;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@PostMapping&lt;/span>(value &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;/message&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> DeliveryResponseDTO &lt;span style="color:#a6e22e">sendMessage&lt;/span>(&lt;span style="color:#a6e22e">@RequestBody&lt;/span> MessageRequestDTO message, &lt;span style="color:#a6e22e">@RequestParam&lt;/span> NotificationTypeEnum delivery) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log.&lt;span style="color:#a6e22e">info&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Message received. Method of delivery: &amp;#34;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> delivery &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">&amp;#34;. Payload: &amp;#34;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> message);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> notificationService.&lt;span style="color:#a6e22e">redirectMessage&lt;/span>(message, delivery);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Criamos uma classe &lt;code>MessageRequestDTO&lt;/code> que encapsula uma mensagem de tipo String e uma classe enum chamada &lt;code>NotificationTypeEnum&lt;/code> com todas as nossas opções de entrega.&lt;/p>
&lt;p>A interface que especifica nosso método de entrega padrão para todas as opções de entrega é a seguinte:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span> &lt;span style="color:#a6e22e">Notification&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> DeliveryResponseDTO &lt;span style="color:#a6e22e">deliverMessage&lt;/span>(MessageRequestDTO message);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>E este é um exemplo de nossa classe de entrega implementando a interface &lt;code>Notification&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@Slf4j&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CarrierPigeonNotification&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> Notification {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> DeliveryResponseDTO &lt;span style="color:#a6e22e">deliverMessage&lt;/span>(MessageRequestDTO message) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log.&lt;span style="color:#a6e22e">info&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Carrier Pigeon is the selected choice of delivery! The message to send is: &amp;#34;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> message);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> DeliveryResponseDTO.&lt;span style="color:#a6e22e">builder&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">delivered&lt;/span>(&lt;span style="color:#66d9ef">false&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">deliveryStatus&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Delivery method not yet supported!&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">build&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Maravilha, agora vamos criar a classe &lt;code>NotificationService&lt;/code> que tratará o envio da nossa requisição de mensagem vinda do controller.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@NoArgsConstructor&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@Service&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">NotificationService&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> DeliveryResponseDTO &lt;span style="color:#a6e22e">redirectMessage&lt;/span>(MessageRequestDTO message, NotificationTypeEnum methodOfDelivery){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Notification notification &lt;span style="color:#f92672">=&lt;/span> methodOfDelivery.&lt;span style="color:#a6e22e">getInstance&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> notification.&lt;span style="color:#a6e22e">deliverMessage&lt;/span>(message);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Pera aí&amp;hellip; &lt;em>Não tem muita coisa acontecendo aqui.&lt;/em> Criamos um método para redirecionar a mensagem recebendo o próprio DTO de mensagem e o método de entrega, que é um enum. Aparentemente, existe um método dentro do nosso enum para obter a instância do &lt;code>NotificationType&lt;/code>&amp;hellip; Vamos dar uma olhada em como a classe enum foi criada.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">enum&lt;/span> NotificationTypeEnum {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CARRIER_PIGEON {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> CarrierPigeonNotification &lt;span style="color:#a6e22e">getInstance&lt;/span>(){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> CarrierPigeonNotification();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> EMAIL {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> EmailNotification &lt;span style="color:#a6e22e">getInstance&lt;/span>(){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> EmailNotification();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> MAIL_LETTER {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> MailLetterNotification &lt;span style="color:#a6e22e">getInstance&lt;/span>(){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> MailLetterNotification();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> MOBILE_PUSH {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> MobilePushNotification &lt;span style="color:#a6e22e">getInstance&lt;/span>(){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> MobilePushNotification();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> SMS{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> SMSNotification &lt;span style="color:#a6e22e">getInstance&lt;/span>(){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> SMSNotification();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">abstract&lt;/span> Notification &lt;span style="color:#a6e22e">getInstance&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Essa é a classe mais interessante de todo o projeto, na minha opinião. Estamos aplicando um conceito bem legal aqui - criando um método &lt;code>getInstance&lt;/code> que retorna a classe correta de entrega com base no enum enviado pelo usuário. Dessa forma, evitamos blocos &lt;em>if&lt;/em> e nosso código se torna mais limpo e eficiente.&lt;/p>
&lt;p>É possível notar que não tivemos que chamar nenhuma de nossas classes de entrega - nem as classes de service nem de controller precisaram chamar. Se quiséssemos adicionar um novo tipo de entrega, não teríamos que mexer em nenhuma das outras classes de tipo de entrega, elas nem &amp;ldquo;perceberiam&amp;rdquo; a adição ou remoção de tal método de entrega. Isso acontece porque nossa lógica de construção das instancias das classes é mantida por apenas uma classe usada como &amp;ldquo;fábrica&amp;rdquo;, neste caso, a &lt;code>NotificationTypeEnum&lt;/code>.&lt;/p>
&lt;p>Então, para simplificar, o Factory funciona criando uma interface que é responsável por criar &lt;em>famílias&lt;/em> de objetos que possuem a mesma &amp;ldquo;função&amp;rdquo;, mas com comportamento diferente, sem a necessidade de especificar qual é a classe concreta desses objetos. A parte de ser uma fábrica está na criação de mecanismos que tratam de selecionar a implementação correta para cada caso necessário.&lt;/p>
&lt;p>É isso! Você pode conferir a implementação completa desse exemplo de factory &lt;a class="link" href="https://github.com/GracieleDamasceno/design-patterns/tree/main/factory" target="_blank" rel="noopener"
>clicando aqui.&lt;/a>&lt;/p></description></item></channel></rss>