<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Design Patterns on Dev On Track!</title><link>https://blog.devontrack.com/series/design-patterns/</link><description>Recent content in Design Patterns on Dev On Track!</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Sat, 10 Oct 2026 22:28:34 -0300</lastBuildDate><atom:link href="https://blog.devontrack.com/series/design-patterns/index.xml" rel="self" type="application/rss+xml"/><item><title>Design Patterns - Bridge</title><link>https://blog.devontrack.com/posts/2023-03-03-design-pattern-bridge/</link><pubDate>Fri, 03 Mar 2023 08:00:00 +0000</pubDate><guid>https://blog.devontrack.com/posts/2023-03-03-design-pattern-bridge/</guid><description>&lt;p>&lt;em>&lt;strong>Bridge&lt;/strong>&lt;/em> is a structural design pattern that aims to decouple an abstraction of its implementation, in a way that allows both to evolve in an independent way.&lt;/p>
&lt;p>This pattern usage is recommended when dealing with classes have many different implementations and use inheritance to implement the abstraction. In those cases, the inheritance connects an implementation to the abstraction permanently, in a way that it&amp;rsquo;s hard to modify, increase and re-utilize the abstractions in an independent fashion.&lt;/p>
&lt;p>To give an illustrated example, let&amp;rsquo;s pretend that we have a scenario where we want to create different types of bank accounts: &lt;code>CheckingAccount&lt;/code> and &lt;code>SavingsAccount&lt;/code>. We want our system to be flexible to the creation of new accounts types, so we create an abstract class called &lt;code>BankAccount&lt;/code> and extend this class with &lt;code>CheckingAccount&lt;/code> and &lt;code>SavingsAccount&lt;/code> classes.&lt;/p>
&lt;p>Great! Later, we want to give our account types their own personalized credit card type. We create &lt;code>BasicCreditCard&lt;/code>, &lt;code>SilverCreditCard&lt;/code> and &lt;code>GoldCreditCard&lt;/code> classes. When binding those credit card to each bank account type, the problem gets clear:&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>The naive approach would be to create a combination for each account type, a solution which is costly and grows exponentially (imagine how much work if we add a new account type!). The code is also highly coupled, since different states and behaviors would be contained in a single class.&lt;/p>
&lt;p>The Bridge pattern solves this issue by switching from inheritance to composition, and relocating all &lt;code>CreditCard&lt;/code> classes to their own hierarchy. By doing that, we allow both contexts to evolve and change independently.&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>With that design in mind, let&amp;rsquo;s then create the &lt;code>CreditCard&lt;/code> interface:&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>Now, we&amp;rsquo;ll create our types: Basic, Silver and Gold, all implementing the methods specified by the 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>Let&amp;rsquo;s create the abstraction &lt;code>BankAccount&lt;/code>, the base class for our account types. This class will have an object of &lt;code>CreditCard&lt;/code>, as well as a method to get the card information.&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>With all created, we can write our account types &lt;code>CheckingAccount&lt;/code> and &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>To test our design, we&amp;rsquo;ll create a main class initializing each account with their respective credit card types.&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; which outputs the following content:&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>In the end, Bridge pattern is a great tool to be used when we want to divide and refactor classes with a lot of variants, and also when we need to extend a class in independent dimensions. A great benefit in using this pattern is that it follows the &lt;strong>open/closed principle&lt;/strong> (since we can add abstractions and implementations without impacting existing ones) and the &lt;strong>single responsibility principle.&lt;/strong>&lt;/p>
&lt;p>You can check the full implementation of this example &lt;a class="link" href="https://github.com/GracieleDamasceno/design-patterns" target="_blank" rel="noopener"
>here @ my Github: GracieleDamasceno/design-patterns&lt;/a>!&lt;/p>
&lt;h4 id="references">&lt;a href="#references" class="header-anchor">&lt;/a>References:
&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>Design Patterns - Adapter</title><link>https://blog.devontrack.com/posts/2023-02-18-design-pattern-adapter/</link><pubDate>Sat, 18 Feb 2023 08:00:00 +0000</pubDate><guid>https://blog.devontrack.com/posts/2023-02-18-design-pattern-adapter/</guid><description>&lt;p>&lt;em>&lt;strong>Adapter&lt;/strong>&lt;/em> is a design pattern with the purpose of - as the name suggests - adapt one context to another, allowing two incompatible interfaces to be connected.&lt;/p>
&lt;p>The main benefit of applying this pattern is to allow switching from an existing interface to another without changing the original behavior of the existing interface. Adapter is also used when there&amp;rsquo;s the necessity of creating a reusable class that interacts with incompatible interfaces.&lt;/p>
&lt;p>Let&amp;rsquo;s see this pattern in action!&lt;/p>
&lt;h2 id="adapting-an-existing-output-to-a-new-one">&lt;a href="#adapting-an-existing-output-to-a-new-one" class="header-anchor">&lt;/a>Adapting an existing output to a new one
&lt;/h2>&lt;p>In our scenario, we have a Person POJO that contains a few attributes.&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>There&amp;rsquo;s also an interface that dictates the contract of a Person. In our case, the existing contract states that the &lt;code>Person&lt;/code> output should be a string formatted in 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>And the &lt;code>LegacyPersonService&lt;/code> implements that contract, building a &lt;code>Person&lt;/code> object and returning it in XML written as string.&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>This architecture works well for quite a while, until we have to redesign our system. Since we have a lot of external and crucial dependencies, the XML output has to coexist with the new solution, which has the objective to output the Person object as a string in JSON format.&lt;/p>
&lt;p>That&amp;rsquo;s exactly when the adapter pattern comes in handy!&lt;/p>
&lt;p>We are going to adapt our previous solution to generate a JSON, following the new requirements. First, let&amp;rsquo;s implement an interface that carries this new contract.&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>Now, we create the adapter: implementing the interface created earlier, we instantiate the &lt;code>LegacyPersonService&lt;/code> class that contains the logic of the old contract and implement the new logic to transform the response into a string in 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;/p>
&lt;br>
&lt;p>With that created, we can safely create a new version of our endpoint which serves the new specification, without changing the existing one.&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>So, to summarize:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>The adapter pattern follows the &lt;strong>open-closed principle&lt;/strong>. We can add new adapters without altering the existing code.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>The adapter pattern also follows the &lt;strong>single responsibility&lt;/strong> principle, since we separated the interface/contract from the existing business logic.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>In our case, it was used composition at &lt;code>ModernizedPersonAdapter&lt;/code> to wrap the target of the adapter (&lt;code>LegacyPersonService&lt;/code>). This way of dealing with the &lt;em>adaptee&lt;/em> class is called &lt;strong>Object Adapter&lt;/strong>.&lt;/p>
&lt;ul>
&lt;li>The other way of implementing an adapter would be using the &lt;strong>Class Adapter&lt;/strong> style, where instead of creating a &lt;code>LegacyPersonService&lt;/code> object in &lt;code>ModernizedPersonAdapter&lt;/code>, we would simultaneously extend &lt;code>LegacyPersonService&lt;/code> and implement &lt;code>PersonOutputAdapter&lt;/code>. Both are valid approaches, however, it&amp;rsquo;s best to favor composition over inheritance, since it allows the system to be easier to test, less complex and decoupled.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>The main disadvantage that this pattern offers is the increase in complexity when adding new components to the application. Depending on the situation and external constraints, it&amp;rsquo;s better to just refactor the existing code to match the new contract.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;br>
&lt;p>You can check the full implementation displayed &lt;a class="link" href="https://github.com/GracieleDamasceno/design-patterns" target="_blank" rel="noopener"
>here @ my Github: GracieleDamasceno/design-patterns&lt;/a>! Till next time!&lt;/p>
&lt;br>
&lt;h2 id="references">&lt;a href="#references" class="header-anchor">&lt;/a>References:
&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>Design Patterns - Prototype</title><link>https://blog.devontrack.com/posts/2022-11-04-design-pattern-prototype/</link><pubDate>Fri, 04 Nov 2022 08:00:00 +0000</pubDate><guid>https://blog.devontrack.com/posts/2022-11-04-design-pattern-prototype/</guid><description>&lt;p>Following our series of design patterns, the second one that we will revisit is Prototype!&lt;/p>
&lt;p>This pattern aims to have a “blueprint” to generate instances. This is very handy in situations where exists multiple objects with different properties, it is expensive to create new resources and when we want to specify the class instantiation during run-time.&lt;/p>
&lt;p>Basically, to implement a Prototype, we have to add to the desired original class a method that clones an instance based on the original. The next step is to create a “registry” that maintains a cache of the prototypical objects; followed by a factory class that clones the original and returns the result.&lt;/p>
&lt;p>The clone process is a main aspect of prototype, so, to better understand the nuances hidden in cloning an object, let&amp;rsquo;s talk about deep cloning and 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> means when cloning, each copy will have their own reference. If we change an attribute of the copy, the original will remain intact.&lt;/p>
&lt;p>The same doesn&amp;rsquo;t happen when &lt;strong>shallow cloning&lt;/strong>: both copy and original shares the same reference. This means that changes made to copy attributes will also be reflected in the original attributes object.&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="implementing-prototype-pattern-in-java">&lt;a href="#implementing-prototype-pattern-in-java" class="header-anchor">&lt;/a>Implementing Prototype Pattern in Java
&lt;/h2>&lt;p>There&amp;rsquo;s a few “&lt;em>gotchas&lt;/em>” while implementing Prototype in Java: The obvious choice, Java&amp;rsquo;s &lt;code>Cloneable&lt;/code> interface, is commonly known to be flawed. There&amp;rsquo;s simply no built mechanism in Java to create deep copies, which means that implementing &lt;code>Cloneable&lt;/code> and calling &lt;code>super.clone()&lt;/code> will always create a shallow copy either way. Even worse, the interface &lt;code>Cloneable&lt;/code> is a marker class that just marks the class that implements it as suitable for cloning, and doesn&amp;rsquo;t have itself a &lt;code>clone()&lt;/code> method (this method being presented in the Object class instead).&lt;/p>
&lt;p>Those factors argue to be a better choice to use copy constructors to create a clone instead of Java&amp;rsquo;s Cloneable.&lt;/p>
&lt;p>With that in mind, let&amp;rsquo;s attempt to use Prototype to solve a problem. The concept is as follows: We want to keep track of some Cryptocurrencies that were bought on January 1st, 2022. The snapshot of the values at this period of time populates the original instance when the application starts. The user sends their choice of Cryptocurrency and the application calls an endpoint to get real-time information about that specific Crypto, calculates the difference between then and now in a report.&lt;/p>
&lt;p>This is the application architecture diagram:&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>The application controller is as follows:&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>The controller will then call the 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>This is the class that mappers the object received by the request to the instance 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>The class that loads the original instance of 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>Finally, the Cryptocurrency class that performs the cloning in the constructor:&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>You can check the full project implementation &lt;a class="link" href="https://github.com/GracieleDamasceno/design-patterns/tree/main/prototype" target="_blank" rel="noopener"
>clicking here.&lt;/a>&lt;/p>
&lt;h2 id="references">&lt;a href="#references" class="header-anchor">&lt;/a>References
&lt;/h2>&lt;p>Interesting conversations about Java&amp;rsquo;s Cloneable:&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>Design Patterns - Factory</title><link>https://blog.devontrack.com/posts/2022-08-29-design-pattern-factory/</link><pubDate>Mon, 29 Aug 2022 08:00:00 +0000</pubDate><guid>https://blog.devontrack.com/posts/2022-08-29-design-pattern-factory/</guid><description>&lt;p>Today we are going to take a close look at Factory Design Pattern.&lt;/p>
&lt;p>Imagine that you have a requirement to build an application feature that sends a message specified by a user through different delivery methods. For example, they can send their message using SMS, push notification to a mobile phone, email&amp;hellip;&lt;/p>
&lt;p>It would be such a hassle to build different classes to receive the user message to deliver it! I mean, imagine if the user has to memorize different endpoints/arguments to send their message. Looking at the code, we would have to create a method that would call each of the classes that would send a message using a specific way. But what if I want to develop another message delivery type? I would have to touch the logic that controls each message to their respective type, and if I&amp;rsquo;m not careful enough, I could delete or modify important pieces of that logic. My code would have lots of conditions and could be highly coupled.&lt;/p>
&lt;p>The Factory Patterns suggests a pretty neat way to solve that problem. Let&amp;rsquo;s see how!&lt;/p>
&lt;h3 id="show-me-the-code">&lt;a href="#show-me-the-code" class="header-anchor">&lt;/a>Show me the code!
&lt;/h3>&lt;p>First, let&amp;rsquo;s take a look at our architecture diagram.&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>The main idea is to create a notification interface that will have a delivery method defined, so that each of the classes will implement their own specifics of the delivery. There&amp;rsquo;s five delivery method defined, and those methods will be called based on a parameter sent by the user through a service. We will get more details about it in a bit.&lt;/p>
&lt;p>The project uses Java with Spring and a &lt;code>REST&lt;/code> call to send a message. Let&amp;rsquo;s start by creating a &lt;code>REST&lt;/code> controller where the user can post their message and the selected delivery type.&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>We have created a &lt;code>MessageRequestDTO&lt;/code> that encapsulates a String attribute message, and an enum class called &lt;code>NotificationTypeEnum&lt;/code> with all of our delivery options.&lt;/p>
&lt;p>The interface that specifies our delivery method is as follows:&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>And this is an example of our delivery class implementing &lt;code>Notification&lt;/code> interface:&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>Great, now, let&amp;rsquo;s create the class &lt;code>NotificationService&lt;/code> that will handle the dispatch of our message request from the 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>Hang on&amp;hellip; &lt;em>There&amp;rsquo;s not much happening here.&lt;/em> We created a method to redirect the message by receiving the message itself and the method of delivery, which is an enum. Apparently, there&amp;rsquo;s a method inside our enum to get the instance of the &lt;code>NotificationType&lt;/code>&amp;hellip; Let&amp;rsquo;s take a closer look at how the enum class was created.&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>This is the most interesting class in the project, in my opinion. We are applying a cool concept here - creating a &lt;code>getInstance&lt;/code> method which redirects returns the correct class of delivery based on the enum sent by the user. That way, we avoid if statements and our code becomes more clean and efficient.&lt;/p>
&lt;p>It&amp;rsquo;s possible to notice that we didn&amp;rsquo;t have to call any of our delivery classes - neither any of the service nor controller classes had to. If we wanted to add a new delivery type, we wouldn&amp;rsquo;t have to touch any of the other delivery classes, they wouldn&amp;rsquo;t even &amp;ldquo;notice&amp;rdquo; the addition or removal of such delivery method. This happens because our logic of constructing a class is held by only one &amp;ldquo;factory&amp;rdquo; class, in this case, &lt;code>NotificationTypeEnum&lt;/code>.&lt;/p>
&lt;p>So, to put it simply, Factory works by creating an interface that creates families of objects that have the similar function but different behavior, without the need of specifying the concrete class of those objects. The Factory-part lies in creating mechanisms that deal with selecting the correct implementation for each case needed.&lt;/p>
&lt;p>That&amp;rsquo;s it! You can check the full project implementation &lt;a class="link" href="https://github.com/GracieleDamasceno/design-patterns/tree/main/factory" target="_blank" rel="noopener"
>clicking here.&lt;/a>&lt;/p></description></item></channel></rss>