From f6942cf18dab21b354be69a3853c12f6d21b7a60 Mon Sep 17 00:00:00 2001 From: swarajsaaj Date: Thu, 10 Sep 2020 02:57:56 +0530 Subject: [PATCH 1/4] #1313 Add Separated Interface design pattern --- separated-interface/README.md | 119 ++++++++++++++++++ separated-interface/etc/class_diagram.png | Bin 0 -> 32651 bytes .../etc/separated-interface.urm.puml | 36 ++++++ separated-interface/pom.xml | 71 +++++++++++ .../com/iluwatar/separatedinterface/App.java | 61 +++++++++ .../invoice/InvoiceGenerator.java | 28 +++++ .../invoice/TaxCalculator.java | 30 +++++ .../separatedinterface/taxes/DomesticTax.java | 40 ++++++ .../separatedinterface/taxes/ForeignTax.java | 40 ++++++ .../iluwatar/separatedinterface/AppTest.java | 41 ++++++ .../invoice/InvoiceGeneratorTest.java | 25 ++++ .../taxes/DomesticTaxTest.java | 18 +++ .../taxes/ForeignTaxTest.java | 18 +++ 13 files changed, 527 insertions(+) create mode 100644 separated-interface/README.md create mode 100644 separated-interface/etc/class_diagram.png create mode 100644 separated-interface/etc/separated-interface.urm.puml create mode 100644 separated-interface/pom.xml create mode 100644 separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java create mode 100644 separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/InvoiceGenerator.java create mode 100644 separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/TaxCalculator.java create mode 100644 separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTax.java create mode 100644 separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTax.java create mode 100644 separated-interface/src/test/java/com/iluwatar/separatedinterface/AppTest.java create mode 100644 separated-interface/src/test/java/com/iluwatar/separatedinterface/invoice/InvoiceGeneratorTest.java create mode 100644 separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxTest.java create mode 100644 separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxTest.java diff --git a/separated-interface/README.md b/separated-interface/README.md new file mode 100644 index 000000000..11ad4a978 --- /dev/null +++ b/separated-interface/README.md @@ -0,0 +1,119 @@ +--- +layout: pattern +title: Separated Interface +folder: separated-interface +permalink: /patterns/separated-interface/ +categories: Architectural +tags: + - Decoupling +--- + + +## Intent +Separate the interface definition and implementation in different packages. This allows the client to be completly unaware of the implementation. + +## Explanation + +Real world example + +> An Invoice generator may be created with ability to use different Tax calculators that may be added in the invoice depending upon type of purchase, region etc. + +In plain words + +> Separated interface pattern encourages to keep the implementations of an interface decoupled from the client and its definition, so the client is not dependent on the implementation. + +A client code may abstract some specific functionality to an interface, and define the definition of the interface as an SPI. Another package may implement this interface definition with a concrete logic, which will be injected into the client code at runtime (with a third class, injecting the implementation in the client) or at compile time (using Plugin pattern with some configurable file). + +**Programmatic Example** + +**Client** An Invoice generator class accepts the cost of the product and calculates the total amount payable inclusive of tax + +```java +public class InvoiceGenerator { + + private final TaxCalculator taxCalculator; + + private final double amount; + + public InvoiceGenerator(double amount, TaxCalculator taxCalculator) { + this.amount = amount; + this.taxCalculator = taxCalculator; + } + + public double getAmountWithTax() { + return amount + taxCalculator.calculate(amount); + } + +} +``` +The tax calculation logic is delegated to the ```TaxCalculator``` interface + +```java + +public interface TaxCalculator { + + double calculate(double amount); + +} + +``` + +**Implementation package** +In another package (which the client is completely unaware of) there exist multiple implementations of the ```TaxCalculator``` interface +```ForeignTax``` which levies 60% tax for international products. +```java +public class ForeignTax implements TaxCalculator { + + public static final double TAX_PERCENTAGE = 60; + + @Override + public double calculate(double amount) { + return amount * TAX_PERCENTAGE / 100.0; + } + +} +``` + +```DomesticTax``` which levies 20% tax for international products. +```java +public class DomesticTax implements TaxCalculator { + + public static final double TAX_PERCENTAGE = 20; + + @Override + public double calculate(double amount) { + return amount * TAX_PERCENTAGE / 100.0; + } + +} +``` + +These both implementations are instantiated and injected in the client class by the ```App.java``` class + +```java + var internationalProductInvoice = new InvoiceGenerator(PRODUCT_COST, new ForeignTax()); + + LOGGER.info("Foreign Tax applied: {}", "" + internationalProductInvoice.getAmountWithTax()); + + var domesticProductInvoice = new InvoiceGenerator(PRODUCT_COST, new DomesticTax()); + + LOGGER.info("Domestic Tax applied: {}", "" + domesticProductInvoice.getAmountWithTax()); +``` + +## Class diagram +![alt text](./etc/class_diagram.png "Separated Interface") + +## Applicability +Use the Separated interface pattern when + +* You are developing a framework package, and your framework needs to call some application code through interfaces. +* You have separate packages implementing the functionalities which may be plugged in your client code at runtime or compile-time. +* Your code resides in a layer that is not allowed to call the interface implementation layer by rule. For example, a domain layer needs to call a data mapper. + +## Tutorial + +* [Separated Interface Tutorial](https://www.youtube.com/watch?v=d3k-hOA7k2Y) + +## Credits + +* [Martin Fowler](https://www.martinfowler.com/eaaCatalog/separatedInterface.html) diff --git a/separated-interface/etc/class_diagram.png b/separated-interface/etc/class_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..a0edbac8dac3cd5a0f1dd174fd1cfaa0bbc78e72 GIT binary patch literal 32651 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

@OZmh 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 "-taxCalculator" TaxCalculator +DomesticTax ..|> TaxCalculator +ForeignTax ..|> TaxCalculator +@enduml \ No newline at end of file diff --git a/separated-interface/pom.xml b/separated-interface/pom.xml new file mode 100644 index 000000000..da7584a93 --- /dev/null +++ b/separated-interface/pom.xml @@ -0,0 +1,71 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.24.0-SNAPSHOT + + separated-interface + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.mockito + mockito-core + test + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.separatedinterface.App + + + + + + + + + diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java new file mode 100644 index 000000000..e0a385c9e --- /dev/null +++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java @@ -0,0 +1,61 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.separatedinterface; + +import com.iluwatar.separatedinterface.invoice.InvoiceGenerator; +import com.iluwatar.separatedinterface.taxes.DomesticTax; +import com.iluwatar.separatedinterface.taxes.ForeignTax; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + *

The Strategy pattern (also known as the policy pattern) is a software design pattern that + * enables an algorithm's behavior to be selected at runtime.

+ * + *

Before Java 8 the Strategies needed to be separate classes forcing the developer + * to write lots of boilerplate code. With modern Java it is easy to pass behavior with method + * references and lambdas making the code shorter and more readable.

+ * + */ +public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + public static final double PRODUCT_COST = 50.0; + + /** + * Program entry point. + * + * @param args command line args + */ + public static void main(String[] args) { + //Create the invoice generator with product cost as 50 and foreign product tax + var internationalProductInvoice = new InvoiceGenerator(PRODUCT_COST, new ForeignTax()); + LOGGER.info("Foreign Tax applied: {}", "" + internationalProductInvoice.getAmountWithTax()); + + //Create the invoice generator with product cost as 50 and domestic product tax + var domesticProductInvoice = new InvoiceGenerator(PRODUCT_COST, new DomesticTax()); + LOGGER.info("Domestic Tax applied: {}", "" + domesticProductInvoice.getAmountWithTax()); + } +} diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/InvoiceGenerator.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/InvoiceGenerator.java new file mode 100644 index 000000000..f73ee32d8 --- /dev/null +++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/InvoiceGenerator.java @@ -0,0 +1,28 @@ +package com.iluwatar.separatedinterface.invoice; + +/** + * InvoiceGenerator class generates an invoice, accepting the product cost and calculating the total + * price payable inclusive tax (calculated by {@link TaxCalculator}) + */ +public class InvoiceGenerator { + + /** + * The TaxCalculator interface to calculate the payable tax. + */ + private final TaxCalculator taxCalculator; + + /** + * The base product amount without tax. + */ + private final double amount; + + public InvoiceGenerator(double amount, TaxCalculator taxCalculator) { + this.amount = amount; + this.taxCalculator = taxCalculator; + } + + public double getAmountWithTax() { + return amount + taxCalculator.calculate(amount); + } + +} \ No newline at end of file diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/TaxCalculator.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/TaxCalculator.java new file mode 100644 index 000000000..aa4b81a84 --- /dev/null +++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/TaxCalculator.java @@ -0,0 +1,30 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.separatedinterface.invoice; + +public interface TaxCalculator { + + double calculate(double amount); + +} diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTax.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTax.java new file mode 100644 index 000000000..ebe0e306e --- /dev/null +++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTax.java @@ -0,0 +1,40 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.separatedinterface.taxes; + +import com.iluwatar.separatedinterface.invoice.TaxCalculator; + +/** + * TaxCalculator for Domestic goods with 20% tax. + */ +public class DomesticTax implements TaxCalculator { + + public static final double TAX_PERCENTAGE = 20; + + @Override + public double calculate(double amount) { + return amount * TAX_PERCENTAGE / 100.0; + } + +} diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTax.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTax.java new file mode 100644 index 000000000..583f70d3b --- /dev/null +++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTax.java @@ -0,0 +1,40 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.separatedinterface.taxes; + +import com.iluwatar.separatedinterface.invoice.TaxCalculator; + +/** + * TaxCalculator for foreign goods with 60% tax. + */ +public class ForeignTax implements TaxCalculator { + + public static final double TAX_PERCENTAGE = 60; + + @Override + public double calculate(double amount) { + return amount * TAX_PERCENTAGE / 100.0; + } + +} diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/AppTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/AppTest.java new file mode 100644 index 000000000..4114f9bb7 --- /dev/null +++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/AppTest.java @@ -0,0 +1,41 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.separatedinterface; + +import org.junit.jupiter.api.Test; + +import com.iluwatar.separatedinterface.App; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +/** + * Application test. + */ +class AppTest { + + @Test + void shouldExecuteWithoutException() { + assertDoesNotThrow(() -> App.main(new String[]{})); + } +} diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/invoice/InvoiceGeneratorTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/invoice/InvoiceGeneratorTest.java new file mode 100644 index 000000000..669fb1452 --- /dev/null +++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/invoice/InvoiceGeneratorTest.java @@ -0,0 +1,25 @@ +package com.iluwatar.separatedinterface.invoice; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.mockito.Mockito.*; + +public class InvoiceGeneratorTest { + + private InvoiceGenerator target; + + @Test + public void testGenerateTax() { + var productCost = 50.0; + var tax = 10.0; + TaxCalculator taxCalculatorMock = mock(TaxCalculator.class); + doReturn(tax).when(taxCalculatorMock).calculate(productCost); + + target = new InvoiceGenerator(productCost, taxCalculatorMock); + + Assertions.assertEquals(target.getAmountWithTax(), productCost + tax); + verify(taxCalculatorMock, times(1)).calculate(productCost); + } + +} diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxTest.java new file mode 100644 index 000000000..e562586c2 --- /dev/null +++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxTest.java @@ -0,0 +1,18 @@ +package com.iluwatar.separatedinterface.taxes; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class DomesticTaxTest { + + private DomesticTax target; + + @Test + public void testTaxCaluclation(){ + target = new DomesticTax(); + + var tax=target.calculate(100.0); + Assertions.assertEquals(tax,20.0); + } + +} diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxTest.java new file mode 100644 index 000000000..86bf39e80 --- /dev/null +++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxTest.java @@ -0,0 +1,18 @@ +package com.iluwatar.separatedinterface.taxes; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ForeignTaxTest { + + private ForeignTax target; + + @Test + public void testTaxCaluclation(){ + target = new ForeignTax(); + + var tax=target.calculate(100.0); + Assertions.assertEquals(tax,60.0); + } + +} From 7fd7735527c987a3f65b6c4ec57acdb1d305c3bc Mon Sep 17 00:00:00 2001 From: swarajsaaj Date: Thu, 10 Sep 2020 03:10:58 +0530 Subject: [PATCH 2/4] #1313 Add separated-interface module to parent pom --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index da3084ab2..102668588 100644 --- a/pom.xml +++ b/pom.xml @@ -196,6 +196,7 @@ transaction-script filterer factory + separated-interface From a2967c5a40bacc06f60b699507c3b66c60da6699 Mon Sep 17 00:00:00 2001 From: swarajsaaj Date: Thu, 10 Sep 2020 03:22:00 +0530 Subject: [PATCH 3/4] #1313 Add documentation and license header --- separated-interface/README.md | 2 +- .../com/iluwatar/separatedinterface/App.java | 12 ++++----- .../invoice/InvoiceGenerator.java | 25 ++++++++++++++++++- .../invoice/InvoiceGeneratorTest.java | 23 +++++++++++++++++ .../taxes/DomesticTaxTest.java | 23 +++++++++++++++++ .../taxes/ForeignTaxTest.java | 23 +++++++++++++++++ 6 files changed, 100 insertions(+), 8 deletions(-) diff --git a/separated-interface/README.md b/separated-interface/README.md index 11ad4a978..b26d5c7da 100644 --- a/separated-interface/README.md +++ b/separated-interface/README.md @@ -10,7 +10,7 @@ tags: ## Intent -Separate the interface definition and implementation in different packages. This allows the client to be completly unaware of the implementation. +Separate the interface definition and implementation in different packages. This allows the client to be completely unaware of the implementation. ## Explanation diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java index e0a385c9e..67eeec054 100644 --- a/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java +++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java @@ -30,13 +30,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - *

The Strategy pattern (also known as the policy pattern) is a software design pattern that - * enables an algorithm's behavior to be selected at runtime.

- * - *

Before Java 8 the Strategies needed to be separate classes forcing the developer - * to write lots of boilerplate code. With modern Java it is easy to pass behavior with method - * references and lambdas making the code shorter and more readable.

+ *

The Separated Interface pattern encourages to separate the interface definition and + * implementation in different packages. This allows the client to be completely unaware of the + * implementation.

* + *

In this class the {@link InvoiceGenerator} class is injected with different instances of + * {@link com.iluwatar.separatedinterface.invoice.TaxCalculator} implementations located in separate + * packages, to receive different responses for both of the implementations.

*/ public class App { diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/InvoiceGenerator.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/InvoiceGenerator.java index f73ee32d8..c17ed5ac5 100644 --- a/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/InvoiceGenerator.java +++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/InvoiceGenerator.java @@ -1,8 +1,31 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package com.iluwatar.separatedinterface.invoice; /** * InvoiceGenerator class generates an invoice, accepting the product cost and calculating the total - * price payable inclusive tax (calculated by {@link TaxCalculator}) + * price payable inclusive tax (calculated by {@link TaxCalculator}). */ public class InvoiceGenerator { diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/invoice/InvoiceGeneratorTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/invoice/InvoiceGeneratorTest.java index 669fb1452..ac75d3b70 100644 --- a/separated-interface/src/test/java/com/iluwatar/separatedinterface/invoice/InvoiceGeneratorTest.java +++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/invoice/InvoiceGeneratorTest.java @@ -1,3 +1,26 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package com.iluwatar.separatedinterface.invoice; import org.junit.jupiter.api.Assertions; diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxTest.java index e562586c2..d070d8b0a 100644 --- a/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxTest.java +++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxTest.java @@ -1,3 +1,26 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package com.iluwatar.separatedinterface.taxes; import org.junit.jupiter.api.Assertions; diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxTest.java index 86bf39e80..df184276c 100644 --- a/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxTest.java +++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxTest.java @@ -1,3 +1,26 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package com.iluwatar.separatedinterface.taxes; import org.junit.jupiter.api.Assertions; From 9088ac51f6105f82e4c04c31de262e7e59f3fa8e Mon Sep 17 00:00:00 2001 From: swarajsaaj Date: Sat, 12 Sep 2020 22:35:40 +0530 Subject: [PATCH 4/4] #1313 Rename DomesticTax,ForeignTax and review fixes --- separated-interface/README.md | 16 ++++++++-------- separated-interface/etc/class_diagram.png | Bin 32651 -> 32958 bytes .../etc/separated-interface.urm.puml | 12 ++++++------ .../com/iluwatar/separatedinterface/App.java | 9 +++++---- ...ticTax.java => DomesticTaxCalculator.java} | 2 +- ...eignTax.java => ForeignTaxCalculator.java} | 2 +- ...st.java => DomesticTaxCalculatorTest.java} | 8 ++++---- ...est.java => ForeignTaxCalculatorTest.java} | 8 ++++---- 8 files changed, 29 insertions(+), 28 deletions(-) rename separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/{DomesticTax.java => DomesticTaxCalculator.java} (95%) rename separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/{ForeignTax.java => ForeignTaxCalculator.java} (96%) rename separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/{DomesticTaxTest.java => DomesticTaxCalculatorTest.java} (89%) rename separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/{ForeignTaxTest.java => ForeignTaxCalculatorTest.java} (89%) diff --git a/separated-interface/README.md b/separated-interface/README.md index b26d5c7da..ca7a12e44 100644 --- a/separated-interface/README.md +++ b/separated-interface/README.md @@ -3,7 +3,7 @@ layout: pattern title: Separated Interface folder: separated-interface permalink: /patterns/separated-interface/ -categories: Architectural +categories: Structural tags: - Decoupling --- @@ -22,7 +22,7 @@ In plain words > Separated interface pattern encourages to keep the implementations of an interface decoupled from the client and its definition, so the client is not dependent on the implementation. -A client code may abstract some specific functionality to an interface, and define the definition of the interface as an SPI. Another package may implement this interface definition with a concrete logic, which will be injected into the client code at runtime (with a third class, injecting the implementation in the client) or at compile time (using Plugin pattern with some configurable file). +A client code may abstract some specific functionality to an interface, and define the definition of the interface as an SPI ([Service Programming Interface](https://en.wikipedia.org/wiki/Service_provider_interface) is an API intended and open to be implemented or extended by a third party). Another package may implement this interface definition with a concrete logic, which will be injected into the client code at runtime (with a third class, injecting the implementation in the client) or at compile time (using Plugin pattern with some configurable file). **Programmatic Example** @@ -60,9 +60,9 @@ public interface TaxCalculator { **Implementation package** In another package (which the client is completely unaware of) there exist multiple implementations of the ```TaxCalculator``` interface -```ForeignTax``` which levies 60% tax for international products. +```ForeignTaxCalculator``` which levies 60% tax for international products. ```java -public class ForeignTax implements TaxCalculator { +public class ForeignTaxCalculator implements TaxCalculator { public static final double TAX_PERCENTAGE = 60; @@ -74,9 +74,9 @@ public class ForeignTax implements TaxCalculator { } ``` -```DomesticTax``` which levies 20% tax for international products. +```DomesticTaxCalculator``` which levies 20% tax for international products. ```java -public class DomesticTax implements TaxCalculator { +public class DomesticTaxCalculator implements TaxCalculator { public static final double TAX_PERCENTAGE = 20; @@ -91,11 +91,11 @@ public class DomesticTax implements TaxCalculator { These both implementations are instantiated and injected in the client class by the ```App.java``` class ```java - var internationalProductInvoice = new InvoiceGenerator(PRODUCT_COST, new ForeignTax()); + var internationalProductInvoice = new InvoiceGenerator(PRODUCT_COST, new ForeignTaxCalculator()); LOGGER.info("Foreign Tax applied: {}", "" + internationalProductInvoice.getAmountWithTax()); - var domesticProductInvoice = new InvoiceGenerator(PRODUCT_COST, new DomesticTax()); + var domesticProductInvoice = new InvoiceGenerator(PRODUCT_COST, new DomesticTaxCalculator()); LOGGER.info("Domestic Tax applied: {}", "" + domesticProductInvoice.getAmountWithTax()); ``` diff --git a/separated-interface/etc/class_diagram.png b/separated-interface/etc/class_diagram.png index a0edbac8dac3cd5a0f1dd174fd1cfaa0bbc78e72..10d509801f79b7c9172c87731233d6753d597efd 100644 GIT binary patch literal 32958 zcmcG$WmuJ47dDC_A&8)qBB|1igfxgWNOws|v*-@#F6r)W>6R9d?v`$lZa8!4-n#eu zzUQ3l`||-kyriiQ&HWMXG+bQHeZ^0{#tQFX)U=7J& z_}DCI`dIeB`>QB-(6SXV2D%SNAARwdOPNLy81PJb_n3jMYJ_SjTkiIWcRH`$Ot9&+ z2i@nKTpCjHom8sKC3&9*nHB>tz1n?@GejC)ENun0mo`E&F9Snlji0Tr2O{-gE@(d+ zt`-Zc$fd&L8@aGxe;}~)U1nqxo;H9>sI2r6_xRUlv1tGCx4RcRlcJehBF{egT}UYT zDBkdoY8Wf##YWW;omW#>3x`dfEb#8s$;H~LvS`(#+Nh^BEgKIVCD(^0 zX2mj@C`gH?4HQ(D9%$;E8k&nMCM4wSy?G+bk2oTRQ^+7qRRp=9L~|OzU5$(WemFko z*oF3~H0^s9Et{2(Znq8N7_*fyddFbo>ANFI;>;jDbRoZ!Mdn`AY2QGKOGq@!cVuK)Z37bZScV{DU`nqXG=)o&toA7Ou&+&U}=Uk^R!@FL__u3vbR@J>C zG6nAS>n8(;$O-CfzkZw$9z*{AJs~FVBFf)?$apSP|M%BE%D&ZDblzWVw}biUvO81L zI(;8}4G|aZ-retvXpI+G&VDQncZgtMuBlWi1FO)%U!uJxM7;OKfY9lfTHx{CeRPtq zx7c@K21rDss0f^o9zjUKcL>dV1chVz_lS_ZzHJBpr%fstHGw4J+;j4b-@-6{)o zFL&;`^T6Q3wJ0Qev_1PMtJmxfr;{+4E(n<@(LCLq6%4^|a5`tufNrRS9`WuSGYmux z=XX3LbK43CoDN5ls&FShb5tiqrE>Xm%^4XPYss!$YPD7e;le0I>J4$sCQ|}IIPLB2 zQfn2E`9{mNzWqq(vd=sS(a!E=!?{^p9cnpSV|W&G3C=rz2uQ7aYOMFL_32KeP~D^*64%)@AlY1qk!JYE@I@NMxp>X2yUZA z3e7iyqt)Jcr!bTs2L<43Mg5}zUFo95`(c9ksWxo3yH`I>WHqPC4Xg@?_`JWxvp`n5 zBQH;O4tK__V_5FMG~a>$1jl@jH^uYZ!{Mpv`BU2d?&Tia_h?V5Gi=T_8INX<{GE5_ z8XQ$Bjn7A9Bsfndv?aLCby~eqGR5!Tzh555WHd&aWS3^P(Bgb?RO52ZHr-}CoGBXp zE|E>QFM*Yc%6NOC)b;lIG#=9U6bDBne_>%knjJS`rC#Iud@b346&Sq=GM^>KhE-T; zGCh`f;I@z+!X=U)78X`sYcyV@TwypE;Bd9yIh-Y~lJ?e5v(yX)({cb z_0ce;LQ#o$f$kip2 zj-cEOU_Il}^rq$8csi%mT)aj$lrm^2Z475;zo`}MiKJA>5DE)Lzz5C_+YnGL0x_HX ztUJjaWjK=44Bx4JdT(~j{$M#3KdKOmOp*{XSHCP)S!=x|zrkZMA>Xbp=Xl)DeXEmS zurgC)Ic!m?)vj;f^@+G#jI?VvJ0|AIru)W;3| zCFflxipuos7N%XBpmb4=+pEJ75;gyv95M?ZNK?@Z2Xq*;l=p;6?H ztMH?(PY{MSPaUnc520E`G=rPVUE!0?C3gE-ryh=J`h#gKrZZ>Pr}HcMg2A|& z`K>;vu4V~7?^Q4z9spb(nIfW>`j*Gbt#ndoYLgmtbTiX?rH@>L_ptls6 zoJ+RnDm1FqKYB58%CbiDa9`PDvNQ}99z{hy0>HyONfj@uY zpTBovWmQR~ZeNPGgI#1(WkjH+wbPYm!^5@oW)U`DVY9fKPf?F>m8Ptk`>FG}`EV zc}u}b$jB($=(qde#0D62;QD*g`b23udpqobTy#&nyyM9>xzQf?gnR|?y$X}*%JQjt z`$OQ)!*7zgoYx_;vLgYsjZZ!u6q3sC0NWEd{kRjm16I|e_RP3K{bYg}udBb;Ev>o8=6%B6zrgw&Rf8|SX^8^$8q>^%^8Nvy zU=LKw>771aN2pLGtaQtCutZ;o!^i;lc#b!*pBr?tL6k*p>Db&ghub| z$AVS7mygfo)fQVC%g#qTuj`NJ9&<;giVECID@w6W=bQBL+9LZFxjiGISsY_$@XSW}b09_N#?!IwucgbkRxsQSp8In)$ zd|_3Y?p8K5*IsyVz|MnM5tJAao0}V{poi&wsjqYE0WQI zD|-#6N&QenA1>tb&72NsrlX&rLV%Btl*jDUh^*|^TmhMN)R<|4%2u^%HC0<%Td8+6 zUtxIj;&@A`so{O|UGOQBDJeYE#2_y9Ij|nxb3ivW_aZ{P%UM`^OrU1$_R}+i>Siy~ zx0H!j`x1MQ{E8bdL@35rXtnidNRL|-viFk%>Up; zmCcH6@?(_%aa>2Ht>+QUa1`?QUuH3{v)NH3nq@0z)9b^n6nT^_y9PiAP$IE#5)^(> z3}k3@kA_hU;7Ro9u{6jQ{qjgmoAm*=*;5_I0}eGs2UcVBb~6p9eg3fL{Og%gUfq$D zGD4j8!RSRr9Mipy0+@APlT{05cYXtw_&!N z+JZ4)=0D*q1o zm!04mj}=v;-jD=^kv?-DyHDeHfTNA|?Ur{o4qIb|hUBef4Oa&}-$Z^H4VS}??td=B$IGf)kCEOV$3#g&LPA8e0N8*N zaUz+6j0u`(RZ=sZbG3i-2l|PE#p8XF{gX2&WU2`&aJUBXfowznQg_6GIcGYR&u3!q zwLl1dp|gI_w4cYeA4pr`l1>9KFt~3FJ&WJ*X)HDXcDHHS8A3pS3PZ;`TWd|On2ngU zc=qGRkG8hA;muYYi$p3d42<-p_r8d7U2eYuF<|_&>U@aZC=K5T@=2p~iRJzxf1~9Q z4k&exE2)C-!JLJX%Vfno$XW`sn|^$9^L!uPd$Pt-4~qXMFua5?FfsQlkBR31f~GEs z$IxkV!hE?0jTeHj)OA{W!-M565)Xryb0?n1gF^LgPc7E^g23MKctAzm8rGsPiSXs2 zJKWAbiMxrjpDl;GBa9Q$;YbX<_Q}q)V9n`DPjryi$PW^jW)Xl*bfHuwuy)|k2@kel z*ZLA250-_sdD%f}U*KtPxIU2jjM@0L(-|G>q@oZC>^ARm zxwAW47X-Hhs{WG4tGTp|XYTF8I@;PqO!fD9Nu&I)(s_%<}wsi{d~q za8SxH4i4>(2Pdhg3#~rqBI+NTKiomo!sQC3qVqcsvwOM^L;#qF;7lLfZC=j7DEir> zzWOc>p6FkK;28_P@Y7C#=f4)$nrnSvhYkbt@%i>0%?~ft;qe(^U`VyOejO_2ln!?8 z9t=zhq9aetQ@?081QeJrT`{OrVRo?ZiB~zleFU{N3|R|4+6RF}-S51xFlG#^9w+bL z)$gg+TQGCox5(O6t?iyit8Arho&VqOHh(t&GPU@m_aDYdi3m;KlC1Mb)!-$)U!T-NEyQt3uOx6CCa4)a<0; z-!>h5VRT*)!_d1HtzVlWQ~Z@R{Dneq@C8%w%@9N6H`go!ovsg#+F5?=Z;B8E;wEj| zjy8tH-~HNm>UjJ&JTwflp<_xa?JpRT@4Fmj6faZmx6x5mdl90$t9nC?N&Xn(NPccQ z6eZ!<>ss5~@?&rWHP5fI&$0H#ACSs(B6JBVxUc&r-pcxg6M--|_i*~QcNzLA!H(d31cPjxNtG#qW?v&a(3Z3KH_ zs*Jb*!>UGGQeornE{69nk?Hp|z11P`3G9TO-CwHHJ3f-9@Pw($0OzX#wisyrZEm4y zwo`S*bh(jT#l}mS;a$Z|EQQKTvH#P@@MkOZ`cVxK8U|qBdPf-bwAf3GbJyE>Po!w; zei6cg22jJ?11ejdcTsNUfhWPR~~M~Wak{N5ZxrNrRBg0^h=^egta(@dfI zoz&%w%oP=1?i#-tyvweXJ}*%$`|bVCB%#B%Vbc6PveYVh76$f-myVI90@OcDD01Zs zyOqj5)Y@CdSCi}O{9dzs0u@qtEm@XQn6qsfBM$ zx^)n{;RDzB=k0L9$)_618{F6f7K?gjcb0h_#1{q-P+pQpdVGULNF#9EmMWd;SFSyZ zUrVBlr`IOS++{M7_YX=W924f8Tz<|o*Yo!+Axp(z%H%zrC%SojDIGp#)tt*hrIc&s zheVvKmoYjJn5x=)-p_b$BPOCjBiQ6@zn(3b>7{CL@RZ?F#jv4Ar zXFJ8}lnJ7mG&Zln0v}`9dM1#s>Z<{tX-&=|#FoUxmCIAgpv(Kw@~$B#p;8*pToBP> zgT)J$fH71x7f)x3Xf1=0U9ZnL09&HoQjgT2H;%yJNS|8%6|JEvmDNTQqTvpYOZeZh zf;BbT;A#~;rz$b7Ek;l~1?P`>WsR0HqzqPfiOyc8)W z$30GQdz)z!O1_d{tT~i%69K!{gI#I9bj{k;c#*fYRowJkZg=W9kw$GU%gb_Yao#Td z9gtx@>-8T@>g|1gE1T4KbJ*`KUx=gI8%Hi06-eMT5P_-QP`i>IqC7w&d$Zuv3#6V? z$^_jWtVAy794m|(3|lD46Y8+me+mS<*Ek;{FF z9z}ZI4>p8_g&*M*zngoglX_&6VXAQieA^@y6F6eRHRt%ST#=Ml(TVTV^kuJ|3m4Vf zUT;&1o&3&d1A_bg8?oV=pZ*%4tBGP2Gu zFL>iuHI=_K%R5t+?z+ zN6_$4mN?%vHgzei4G&mt z!{+P#gZT98_x^1~&bxZE4ytHM>7#u#4eeQkq@u;-35O|e7?D%FB++&n)g?($;h&x} z=yrdhsQ>W>?!^44J2D&zyH6B3n#ROoIZQC)^(&g)rn7J+eoTDlBPo%o6@*#`>z<_$ zZkww!q{>>|o+Ed-!-1BC*3ywUS!&3fYV0e$_a5cBJ85=#Q<42iYLs|yhAK^7mFe}j zYzp~Rb>zz!AsjUQ!-wDuG<-#tFB>`F4u?jAk4WB%2F6CO+LtQTOjWrS3WvuT+fS6d zTj{~J&9u66P-NJj1o!lnw_yZ==YuC*Z$JtLsm#Tub3@Kj3yF!5E@{&}`&ojb-@GHc zvWumaVZ6I4n%sad@^fUyFMAC{HAitRM5s7I;s8Rr(IMpL87t)m!zC+_rk&}O=4&jj zvy_dGcXrg???{u=vh@73%#+cRm;pM4djc32- z%6zpBwQ8f&EjlFkF8U6?%0_X0Xs*@9^H+KgqvbQx^P$%}Cu@^=#g-^PUU*5*%4%?V zqGUXOd)aim`JYxO%sW_3tKl}|obA+bdZSQhSEH9z5PJieKNU6ZbW22vB;#;yP4KyB zo1CXD`cXSkkilvx@S!Ivw)Ue;w*0Hn9H~;r(^ExvP|PeDjX%D*ah$d6kGwwU2~kCT z3@POx{F5b*vf2BJk_l95S#2HXn;;D_Up>pe$CBtV_J_|F8NWrB9?i>aXS;dC?lv%B zb#VA7-@s_8!@zn|HhtZ*A!@Qr(AQekJ86EZP9IVs3EU?y4!DonCjz+%N9?yz#tyE* z^r=cDU3Y<42UMW#S=(p3)7a$lqMY`whhJWBK@GbA^c6B-*e)FZNh%o+`2KJcN?AJr z3j5F0i?f4t3H zV!7gAu`vYMofEIOrKNwqNV&1@Uzd}Z*V$c=Kr>6*^sUL>@|jn+@%$^jG0BBe?H(n( zkm84*RUO!+t7tC(y{#PB-Mv;gy>j0|$KF+!ZP-P&Y9=R4PbzIWjI`iR^pP*~S&2!c z+e?j0bl6!RQ!tj7zP=bG?~RHET{Q|Ss>`_sWP|0iF~G1v+;Zo?TP zC`n<9l^wBn3e%)FHvIrn$&6wEt`f5OErg<=6RyG5WlX|2O890jk(+?q;YcqcLi&_u zOpJJ=!T$TB@F624QVxAW6lktg;@f@HxBBYCgY*u;piPoUNr9;}eiI~yu0gfhdgsfN zhedGRF7x);ywFVfp?9RxL`GgH*EstfL@F4l()#<0a3o@95W<-1YQNFENX+%FDaR;7W{M`ibe!PaLQR zWp{V=ba61QKGfVvU@gny^;mnQBXs-i6&$JfWWw%r*4ajl>YZ z99wZG#+2hWe@s2laOntXQcI>bs*kjSm2ncbZCUN*4k4Hik2+lKpmE+MvkE_*nStkA?8KiWiEeqZe8SAzWv2T&vIwiW2xdWl+zP_Aqa?ABR z*tr8cRknhyp7X^prG1OdK*psN664~?;I`y@RZP5?6u1y`m8B* zd)jn4FM4XhfErZ87XzorK2%&8MRP5XWET*gRU&Svksi5D!*zS4QIbe7TS~MhUS*wwT`Tp0-&Cj%}7K0zUlbk8ZP0z{DFb;@QoUq4Z>e}i{u;qK)Ju`tCF-qf zc*aTRw#Kf%f~Tz(M$DHEeU4*NC4X_$c+g!YE1fRDFY>j0jB!_N-&brA1^6NvAkqmx zQrtL@!0x*;e`nzr#Pi})XNGm7$6Si_oN;?MZ;7b_9czxgJ9hMGOUX%l{&j?#4wcTg zB;GDdJ1aW)_-h~(g_1A3xc9NrZQAA9?FEGtii~MgUqk9_dO<*t_i`!cO5Z2%95Cf& zyVK6900L1gIy%U&TC-Kw6uTYXgdNj=9yc*BOY$nHiUxcABFGlVcaxC%27AgC+k*0f z4=BP`wm~?fg*tniz~v|SqcZ?i=8hR{h0+CRD-DL1JAzCw z0><;?lpu?R;9@pfQR5qq<<*qW*3+>djrOk1kqlavC)-M^z0cYOjOXgl*HF3i^CsM{ z?zOQhn9k3IflA2Nw^%%n0YPctU9QE-^p3UrYRs`DG~(GJ5gM$ zrd}U;z%JidpdYlafWj@)5>EQfZK0=4SzRu{~7LjkWC&sX4NWK{Ee4A%tkE#5|v8uCa%P2@1Rt<6)E zU{S5+a}8i&Wgk%VB3X=Mx*I!1*Z2lGh~fRIze@0!_eCbV;JnR;Lt4h?Zp^L@m`Ld< z`U_)`+U@HbY~4-|?bdqZ15CX+9dCMT_XwtjRmhvPS9<)%&JO!^NAsi8$JTG4HAj~C zZSWfHEXUyB60pNA8Sv)&A^JkUoVgwwIDo~*-rqn2R3(fLJG*nPa-&s?2cy~8Z(I#x zMRt8Oo~TQ!{hKQKB`wmUcbF;pu%O3MJs`kSIbph-`B7SmPId>aCv_woxMgjY&^u-M zRDPW^eQg>=Y5a5~zFT2Xj_#+pS>5L)S+@Iae!gasKfaYbYwj?b5c39QFC^r`Y;1v7 z1&hY6w%ISTtR4P3*ZK1K>0U^hSJREMdaksedc&?n-o0~B1OJUOV&oIy33j>TkzmX zL$y}ag}c7tAP27T!t$amXZ}^!G$-2;;BZG3Q7z-*Js`**|64dJe~F)VMU<HkU_8=EO>R?;Mwbr+>i;Se#&U@ znosWWGDrNBHE^!{SeC^$7(RIc<(99Qj5PTTAaO8O`$-2>ZK0x`f1W2>CRDpdVAK3da9OmS4UGfo zZtCa#n5;PegdniwY3hA#vQYPgbiSp|b*A5I$7++2>2i#!0oh6ZJZPQ6dP8h|?~@2* zdwUFZDfdmn(drZL{VH;4)zBmR+sw!t%RAJhF7Vhq_!;9EV_f=Z-n?i!e7{sPV7=sH z6%4pZK8F{NjeaSBEqIbCp!WCvE&uVNwF&?!?Ac0!S`vjgh z6vbM=^_QMmn5W$trPuXIiV78VPpQ@_>|iB8Ay4)>jcJN=2&T)) zB!lH@;K9=7`B673(dUb-zS8U}|46P~Gk191o^!v(0eY(F zTs*jypar^b(9tS`<*zhaHG)zvqc|P0N>%y%o8z^J?(sH8{-u1W$ob>Vd){vVGgNl_ zivr4A4ps((Y3EQ#V-}BRjyYHckX$kfG(kY3vl@i=(GFS&T%P<`48W{L@|QNIsIWdY zO;gmb`D3?Rm+Jpz4OSz@2W2AOuoN%n&@gy@3A1={b`VM>UJM1n(xskgTI18*Tbu+| zOS^Cqrb!F8yEQ<4sJ@tr$3P{b<*?G1O5$K`$Kxkw=0_-0EPcB%#BVrWqlwHD@Giybd_F1BSZ1cKCcZePDg*ql6c&f_qUcHQ;0`6JKCwBn)Z zPy${-2M6SCBcx|s`fX3d9<;`E1n<1thv#RI%Zr$*vrXON#bq%2-YKhIZ8kTW-?TTr z$EQrANY_7A!ClhOb|#2VBK(wr5;Xfla?Ga^;AA8^48=Vo#hDyb^Ebn!iRprjRfUXs;@~H8SyS>=daGwGh~$l zT}KYo4Jnvy+$mQ`-6Ae5m{z0%8-*esi*|l`PNqi6Q|vzKbUF+4zjh(e?>YP(Q1aA| z9MwhYhcgc;_Ops=j3?7Zu#F&(QJayJn3G5)-c30yf7L2-PixCsuMXk9nP_nIE3b!W zKxdxXF?Z()+Ao~jTSTLo!LX+5Ek=qZNhvJne%n&PXU;#u{D>LCy-5)lOGeN)@dx1L zjfz9R{#Z0dORFVcj*`!w3htez=A;_AIU<~PSC?>61i`iL*U+TVj1^FC)yOUqRMac@ zZ)ME3e-z=HDQzq1Ub?S8A{)>~h{!Ce{EEAUEb$@pJ4Y6TZ6o`IsCtho{B`JJ$n|Hy49wmhMQe}KyPEaj00O{u5V z^~D&_Cbl~rq@B`Yn!BShmy*#*CX+<9ri2LksI2ce32(ltyXC~*c~YeTdk^kgu>ybK#-_+oJ& zM!!7nv_EXRH|%qvji4EZ0Ax%JjJ0GwHfdA5+k=26v6(iHmYIIVxWOk%uUz~g+l%px_>_sH5EPBhLE z>ZNo%|B5Puu2f$`?#h0K&rh#2bxZGtYhAHvzA66DtB!=+;{rM&xpX8X35y}|ELA&m zoFQ+>kTlxHs^I~%h6LeYVgh)Nkf`Zg-C;M^B32O>iYc|(K{cd?a<@eG&SnpKV>$c* z%H6cHS}QOVDmp`M|DxT40t-IsYE?hxZWbcO29p;G0i)J~)dXl0nO*2t=HDD>o9;(P~Mx5*uLYv7JsM-(~Q(k=ShADRj525 z?QMoMnL=@C3*dTeGM&cDf!wnaPot`s463Vfbw?#*!B6$gnyqYL4(K{&TxQpN7~$)* ztkJ?);SL<~>SU>QWhXA*zI85MSOp=zEKNl*Ra8qkqx)Ybla~Ro4mhb!;cu-y^?ms7 zrWMGFN`lOFPDc6VB0aLtt+lt5TQYJ8)(DBdVTRvzXZ^s*45_7}%GBChcfpRc9 z{*s?4jOb2i^t&Se7YW1JrMp_dCq~8CmVPdk!ec7k5t!QQZLJmGm!u}T(saepWWCkl zeBngMoH>!A)~0L3yLU`~;_1bX?4BE(aqk^U=?I@wZWFtv80U!d}$*uFMHhV=ZQ!_Kg%l zRz3M+L)uh%&G87ynEv9u)~1U)=Dy1I$Dx=l z?Di&crinyKQ%M_4{DAXsX)tg*xCbtB$68phU~^W??Eq`UrO)5M;O$TDCibWxt7O4L z0Cz~$T-I{`=2Y6SG?c8tXP~IKArf8h4%3EVxD1^d0^-5n4*yWRzTy1r&76_1c2~Dg zP;WG?*bU?$_LWcB)0#FHz0Hy4pl9P~EO_B7Ifi^K{*L4#CbkvfIvUF|&$>tBUs!y0 zx~Kf7=JjSL{3`#aT3~h>@HMDZd}BCOj&iS@2QN-Tca$}{Cog6G=KkBdAf!w#MV+>J6%Pb`rT+$|=t=4XakA@4Kwy z^d(+a$odFVXKB@$K~JJk0zFFnUoZr{m8WSZF++-<3*K@WQ>~P543V#uYiS7ku{@hu zIoroP5SM)=7+gTptNuw&M${vA#Af`pa8@`epd#FPkon4^p^5&7u^jke;dlZmOuuJD zph?;5BjFn-SCgMf6Xx;ar4i*{i6f3Ws@jwACCE`0qTP#RbjZj(G?7&X!!MmL%GquE zH1mNoX(100-JI+30cCWirc5TU04qnx3#YJV#3LEJ3zUHAKu-S{J){R?X8ex36Xh>D zn9GL_X-KxSB%UcLwLe^yzQU@SXel@F0Hg9Z3ca-IGeVrfBgH$jbtRIi^~Or(Xv!p| zyi$hHsLI}%*6TvIfCQ68|HnCC-Hm^x{lBw*%!dHtA|H=XAcuQ2V}qe87K8N)S93*m4R;q4fs;S2G-}KJ%azbkNd z#(S%si+4T`i}z;h=zvEfJyA^6qRNxb(qv~$$ikm3JeG6Xr$^5y-u6j3!@@%8~ZI3cg>jV zUn$nAf*t_SceV)rRvQYO2gtlN7eiP5{i-NewuS-o*4DN{d3qoWDqB#2yzoK+Djyks zwfWMG!U9=WM#)=|6AW#lQaJlS-X0Vj4vA8<9VRC`(rAa2md$`db5bgJZbQvTWwFfa z0K1u#nulo1EQy23&=E60+xVI(eghPky1EDFfAt;kB_t|)2$B)OuSvJmKa*} z=i`Xp5z0&WwU3R_CD0Xcn4fb@B`3U=SWt!Oh|jLsL5rNPldG4-#&=>m(zq)N5?KI;Zl>PxW`X?iPCGrepoW_$p*bT8=*B>9B>-H;BG~V_+oil2a2Yu<)5bh}7QFnDP zp#%}Aaofsciz!Rp7qq<+)P^fZM#1)s41oEY(|0VE;{OP;*{)uEF69T-kz+jnlI8Q zQZ1FvL}D>KTHIfvtj?-5j#V$17?!O8P!HZZ3#)WFUl9Zv4F%9*Hb>`;5?UupXALyi z?&Q_m?!BR4H6vuxXe>z=j2=1w^h&w1pwkeGEHu7PzOfiI$kMOQ*FJlrXpn(!VS{HX zA9o}qP51nMe#Kb10riRIQdxhLxxION9E&R}jp=ivpkN_dUN*Tk=$KIrdDc6;nQC*C z%7PPhRNOQAhH*e^G9BwQnotd5cP+`|<;ovy6s1cV6+eH8Idi}v$F!P29lOs!bgo5>$%OCiFx(RP%1v!z;ars#p_e+hB_DwtR> zjQ`L{!|E4Sic7Q#s9_d?3;QoV2OD>cKGL>D>L!0$ZA%*#b-EMabg_}GSn)G8OK;yy zXy2}Eg7zqJSNx}{5?9v#Mb9?4_}ySs*k9qpX1aIh!Im^h`|W zov05th%2R0uFUm?5^+w8*7lE5@zqI^C>5(852kZZf7WHQ)emBi$|n@Amx_IlI}Li1 zK;Z#e^k@0sZB@yVKZu;W5UhnhALd%kV%CcY;hK>N@Xj>EaFx+!sA_f*U{!1u$PAlq>y3fWU+>Dw{1$lDjvMJ0G#w=YGdm8TJ0>J!&^M zK4leb=y2(q(mwxkcY(U$oHd_vrL1U#{H z)MWZY5um(UApW6qZRac>AfRhW#CHK?ZZ-0z7b}~Tl^xP|$?p#~YFVW+==BjgYl9bP z2-fdSd`^ejW()($f>;-zEJ$wWRM`d66OBo2xzhb%<6YJXGIk#&fb3nxT<0gG1HWuy zN4{&rL=`l6Q^91rI}V*ES)$^&G>!$MO#ar=!rlmn*ge;TuzEc&_x9@}7S&P}*QLBA zrZHd3aOi&}l2OaaeE*kYtdY!>-m=tPWiZDIFgl<3*k~aV8-S9nH?9E#D=N_)-#lLs z?s_7RIpR+>KaCfF$}bx?!~Cjdsq@5tS8^L|RDk0Xg(TV4&1Lat`l$82^}%FwYi5%; z`Evam3ONz$trMC{n;a*~Q#-7FsC*1w(Gcbx0>iILz3c1dRt3*kc3nRRvBJU;OK)>I zo*=TJIW99ApWPLOZNsWYPw^1}ol}G2g;sW{E+9S)*h^ESDQXz^Mjjl`KIcC$2zk_Q zSS#HTp<9I2bCKu0txwLaPzJsyctfu_dk z+?Hn2In%k*qEq)VMD|JND$wj5x%9sZMm9l2HJ@C|9Yu)R>0MJX2R1S05Y6rY*hSBe zjb1Dus8wfYiD|mc+%jJIbZQ4GR7HO;d|hK&h3{hfgjoJVqa@ipH4pvCV}40ABdLC; zGn~T~PS<;#*lN)aB(Kig{pRv|<6TWh)_>yH;}Z~47Z2Nsr9%o7g^(^v$NF$9TqEa(T13Wj736oTl4G#RBvraMB$Eq^}>{=U#)(T`K|#oLWt1eRB&P z5TX1vV=&aq;7q-dk@CSiIBN2TGc|VI^F`{jiw8%=PtD6+D>h(9y!RErcRT3 zOB*`ZQYLvNM;y2czLLUDeEcvs$Jm)k2Qb$33W#5lH5Og!4O3vkvIt!=uvJOC9l3~X zx4eA|Yh8xJEIXU*{84P%68wd=q*(KxN-W@=-8zEfwE`-pYss33{fhuh$EnBzPJeim zBt5TAX#okfYO_E}U7=Cid6OLZbxg01J_{wQ;d)E59bc`(JU7u)?y+*`yhqI(hAqmF2Na@=!~bm*fs~6D7uc3 z@;ImJNQ>=*H<;O|15d;yO|aX;M~bL=FBYbouP{}R_ZfrS7l|-lJ>S>0(4!RI5xx1@ ze0U5|BPHxukp6x0RitHd{AFp!7ZWryj->eGnBT{F>EVWdHJU*cbn?MhS$eIHdeW5- zGBa_q9Ilk%nnxbI{Tz!;(^&4=pUIZog@=frBY&z&KiMWwB4fQ-!u~!;Jy#Y(D;)nq z09H`8mq?@tbk413_=n@7zN_Idf*BDmF}3WwjkFFLf6`njB^>|xl`ZHwhLZ$%chLNw zhMh6gycJTJDOD`1eaDlYH3g@DVLP>Gt&KE5j$a>fHs{x=i!`&9665|C`vN^RZ2a5G zD~&?VD3r(C`=GV(tl{*C3lp%O2zu@H63s-_O>b=E8g>S*>*pqXK4I8t>Mo8 z?S0uK&dJwXtJ|IY1nozC+`H8Ko&1NZL3v7LpUR<=#Xyp;lb#c;MH~vvJ1Ax}^LqE> zKXOZ}&(I~zK+)bcVbqgJxdJL-6FZ5JgXyOhAow)>Wj~#gc6C9jR0rarogk!Iiy%Xy z>yG%ScDirGbqoihFPpZ(4EpldunO^bl5H@Cm&w%GfGv2bkihlvXjsAns;3_zYx>V- zE>Y~J*?hvMgoa`J*hrsvBNhG|$A@>%cR>h3|4)g@Qh1cj_uuceg{rv7`(r22_#Ume z3Lgy1*P9mcBrP_Jf;pN0c0m&U?O6HE_)~_5kTm9m51=Jr+4>lRCV_>^1<8>X6Tun{ zK>_(cV5gGZiMRn3X6Ir`g;-NZp)@pn@kbK=O8={f9%x5TT39_PgUof#qS*urn^*+? zWS6s-7~X^P?IM~nqBgqA(Y|%tJ5x-qpz*wNt04W%KzJ(g*#`~t3z#f004ph}@T+Yy zR-oi3Z7yF_9WW*AP_TV){QgGE$Z(BB0}FNGfDysX$@Y9wMEcTTf2{Boz>QiUNLk2L&NLeVpR$5NQxR@Bv< zT(xzJFaJ)ct$5ljK6f}ScBETqXeD6ga#lyW^viv{Gw4D2X-h8m~tC#)%MWH?7jra18HT=SN z{8&9sO2W0A!#x!9P*nb(*1j?>s;=#K5EX+^2}MdpT0lffN-RK1TBHO7l$7o;009AM z0SN`9TNq-7lrE)n=#F6qhG7_B-Zglu_w&5xoKNQ)%x~|#*1Bq4>x%#4?iP>`zT#Jp zHf@AF!CTE$wV#%3%MRD44ZvzdX_|A!5|bK*rXTO8qF84o*bSPY+ zb_{uN0UoS_VRX`C4kzEJaZ`$OQI&gvzW3?EbfB3)B>=H*{EJDic^hb$OP{!bny zi^3X*kv)zeD+)sHIR0f|~ABn7k)L${@ZlXt*TBs1)#2;O&&y zla9abBfy)!PY}Up{VafnElIj|{xCwNo(lERMJ?nu0}*O8;;7&pgT8spO{u$F-;!Tk zqE>aUt-)htiF}S|IZl<4tIHMl|DIf$|MyIPJ~I#({LxRxlMykyu+eya?Uu9W8(xq* zNKJPKQ(>JW8Xd2lU}6PyvP$se9Ya7H{w7dlxR*761$xw@bQz%h$^55SiF=O24P0 z5pdsl+F&~8QSMi5v~um^r~cm=PTlys6{#rfUd9g+C{^)xipaeg#5r-V0U`3fPe%8x z4d`CHO3-Ya8~?^9=~1mR7s-y9C^mI3GFIueCsuJBtb@a|n$d7ER=SE=D4W4$5dt&c#y< z{deNIe1VC7FHbI}#~qm;NIj_PU*Wddt?|n1XZM``a}IB}R|@av!o!+o-3AM6K@m(R zD2mPew0zA#0u>^%`~w}zRI<516)D2gWMaJ7n0P$$!UJZ}Gl~3$L!gUDpG(^BIp`V6 z;i8gqI%XE5l0+txb@fj;72BCeRQx4ZEf`aPdk<_VnC0K8@t) zSWeXs`{%5H&;6Kxn^+wX9OE2C_pz_~{9r~m8E7rY)WwP|ix3OCY3<=@j(TgclWMnk z){QP1YJN&()BKOj?0?le#G@leS{klD`FgG>UV&@&WtL)Pli!snMzyB(hbNzcNL3Q8 zJM~EPfS}-~?O8V(!lU-{{5EOd(d*-&JAYGs3Y-#(_=DOTc=?#A@A4Pf#j0J9j~6g` zTxwyemAeyqZk`zZe>Ckgm4z-btLW2GaH@{-oH~Q@e1$Ys^))Y`&3_ZpRf}%}q)_Wn zi_B>bgfYhz!-1sO`*tq+y_K9&wt8F@F2=^+)8zL-^VHg5SWyc937osy>!*VBIFn0@38Gjb;3)q@?s zpjRQDIs!Qw3G~WVL8k)-^7lW30&<|-08H#?UMS3`)@BHcI0$ zeU=Q)hI3tscXzMHDZs!&SFisUi&?i7+ff)x;I-+~QE{F@sO{N>Kbhd*wd`*HQeKt+ zLSL?1LLF2Cj78s=EttPZQkT1f9{u#E)9X ztKm70($g-7B#+yQT!(tlYNS$`T?vZ>vuENN7OvPqgW~z5D=iL?S$NJ z%4NR0FmHW*VXkcNI8O>ba$T)bdnr`X4Sm&z1yA$w$j4^`z6Gp7Lcy;2v^8}Zt}jjj zWCQjFkT^)``<=S^8*6TOFS7Jb+<7(SZgXQJFT~dbv3D#o1MR1E8_O}C?pV;nhh_qn5;A0MyF?yk0<{_>^xoQ&LOccMPEYhO@!)uW~st%0#pP5{2-I7-fkY~_ow0% zfJOL!;?n;E`yi9DiESDWuD{4g9wt}qlrV7|pl;T0dkKiGuv`$^M^N-j3@<#!{Ho>c zOy@DYJ`sD|VLGJ3h>^EoLFX{%0?;F5&b)jvflP?U2DMMjV!49#T#%>)5(u~6{@P9q zbhmlV0~7WlSiiM(Z(gG|n~b8qa8je->}GMb1fkQ$Q|#!mFIz;!i5>u!G56Hwg86i( z1kV6K6L?>XVL$Pl&uZd4;bBI4*^-T z!v)v(y*SHekTAZbUd`xxyQ!Us2C*FVox!0&^bG&+8RrvcY_`^=q~x))nNtEeO2#oG zoS)Z^S}$eTJDzMDa5%-MT|8@7xT}R&=cw;MUXvmZEt~o|WWz^>CO22H?x0doSgj*p$Oq-R=Of8`=0Tup2)kWJ71T@(Nr(P%uJ@T;!2 zz+Sp%IdF^leLR`((|Y{>b;cztB^$jwW$1JWM1?U-Z=r#Ubaex;hVIAeXrU0dHvD^X zDvknjR0^>`gzv}zh$lnTASqUxQ0rW-=hLZM3hNNhNwW5^N3nbJKyDvWEG>Up zB5lr(ZT;v6&`<=&s_ZOH(+9|!JEue-lh+Sn8UP9m_)MWQyW+<)RK9rtv#{}l?Umr0 z!Pf>n8#j?{J;*Zq20IGP`qpv7gr`Gt(;L;!YkJY*r zO8rm-tvUd@1r!S&wpwdOKwkT@n9;M}KcKzt1TCDBZ@29YEC8S+ zN0=H9&Po^L4-5oIdjhOj0hVv9sN=N{L4UIyfTGcc-(!0|7y^mk zS{XODO4Ks+M$^~Ga73~zq3!dZ2%R~4Dvv+UAL)eOzvc{EX3 zt}ThW;@%;5)SO_+Ia(BeaCJ`nV%5qEhVII<;5%0T`c9o*)}_gv8m1~?Zz*5IdDb#)%B6Ay^H(H~j^DTE)*L;u-Jqm#w$@gfjAg_`MEH6* zi}8-N)UiO99}YH~{J`MoiEW*)A%RR14(IUU;>YBAV-gNiZFSN(wdB{| z#mg(aR~4<29%N`+5#>W|!)2P+ocHUsBek-JuT0K&>$GcWS$NIj7pn$sHo&yKNdjHY zI3RaBqiJkapHJP)7wYf;ppbm7|uzS%Re!pUw5V_++91?N};?Uuf7329B8B^ZVt+HLqmFB50zpp9aHKptK~9S36^u;B*QW`3d)43X5) z>D%*z?kov4y9kOsXHs9n^-XE6tBAUL=)|fOgXQuJ!c}ilU`mL*hd{a$+Xq9H4U4M{ z&bQTe+m1E^OT9=2fY`!!S~G#MEkBe!2kWQ zHr5-z9=$?b#;sql(_Uk6=b5dbyjGWWGy~)%b1VV*+;O|ogKS@}dJ-y0ehxV~Y314T zCF7#O{{B%QR4FG9*MFNu+ef^*tf~3uu)*+vSxakU!bZ60OVL5XEjR`)Q&hpQe_--{ zC283uEZmihWH2=8OD=x3@*Y@FE%mRVS;s`();FN12jP7J+zQrhx4Jl1rz|0pR}bWG zl>^GgL|eF7EYW%Eo|1!+CRS;|ZqM#t=fIpyncdz$ITD*eX(NIcW^vSSec zUx?gkbnOpI_4M=B4vf_K*Cgw0No$RO%;|-88p6vTIq(M*kU=Z%Q(kh5`-y@r&lQ#(J&U zg4apT+{|T^c6uhalo?S#fZK`GPz*)P>Ou!4CcGy;Bm-j#+5bhKYx7}Qb_%CzV)|Ze zEz#;C$G_)JUK0JBvKjv2!yIW7KVP4xdP$PDk96H2MA*b*^s_Evb-}sfUth>w=s~cO zRmWGCX*Fkd@Y_D$8U|uyn^aM&edN*yBN>i;rE0H*$)Vxc?ftGni1YN1oeCaqP#&?X zMCA0DUz}#JTR@lA%;$|9)ctTs@R@>=oN18@6saK@3hT`&Yo51p+%M=Q@>TVh@RBr? zN}nZrbGz|mAhs(}d`Soa%R;Ifn|P!%Yg4l5(hN+FvF{TFdwztAg{b0gose>dxlH|ZBY`{tVf)+T^&v{`_sra1X!cW4dI}{L zkofYVKDs6wlzO=hy9^Ah0?$dxJK=K2LXKk@y`b4AfY>?}oyl*00j7{Kc56o=|{>5_c40~Se9brAHp)fQ44(F=$1VfE&v1WDv_^+2mQVj-vXmr~z}-_5URWkt}z>?+zbf+Sw(Qhv{dldKqcwAUadlZ+T@%IxtIfTzcQ4)8n-7yx;p-fq( zx7ygg{l9f=2Md;ne6Wqm9zeK*kr0ulf(rl#%p_CNjdHUC4hD2+uC%`VHIL`~&p|d?_+XPR5QoaAg99eQuS5$(t z2HTRCK{dDcBN*ruW0egpS3frhT7lB#BiVC3G0Xj66wnq@3oy1B>FAn@7b7`Tde&b75IyivX`~p+^iqy&p0drH4#6)R?MC_4K zEKb&k?g!iVH#6Eo(wGmG$TwvU?14a-m7nA8D|YS5X7EpmkWR{Ou_N4v_i;Nr+PC(1 z9hjM!2@tqVi9M>I8CuXREpL@)ZavCM7%&S!szz}qi`u>B20-vE zYJrT6U(;BN)Aj)r2wEQ|4=YVD6$d9QUBu2no-T{q?AanOWQE%HEv-;hDvYk@CBywhM(PfPPf z32+wISSZDBd9{|NX6$rAb|{mtBAV%PbvEl|7lb#}6_E#?5`nw~0U;Z^&+~&}$pDm= zlgW;7u%EjJP@pq3h1qe$8RTg3a-o=SJd*gc}Mo}E|&_ay*eu})Tl`ij1$Q~aX{Xq0RYXs%e;Rlxu%6%iTMrB?=y9ZH?<22wAhXdkk;DD+c?Cc=U13GLF~1KGur zwCgW=u5uH0R|O zhCqkPakZ0xTkmH_T{unjz+oYDo7Lvij_!dS^m`INdqH;3JaA|9Dk6t*sJn&<(r^n8 z;LcufI}0KB9ttRgxg16abK>{86W0Nbvg>+ii55Y~6)8m+y(7=T2(k)JdQbxwCkf6r zU=c->cF?G|^Sbbkj^!zK9&_Nmdz0|a)O3!n;+sWaMYKZJtUJccEbcVPms&{i_w2xT zmvmyTv2&+zemTe2GEZonNfb{MOyQKZo5#B$nipQqyL5GgxXn*_nByN{9HFYKJAOv+ zPpA0eagL-sR|!lKIhdQ?19z3}vt9Pj-*Cw^{6=+~<1LWfa{t$x=fjTO+m|wNa!o#& z)Nf5X8ZtDq6@9PVo#|1rJ(aEBa7GpFeLue{gM(&X|wW=!3s}*c8wi>qj z{#czj(qQ3-t}J`qbU2lwhJ%?Q)aia6$YS6I@LlKT3vA)r)mY3_2uT}OjO2m)TNf@B z7Y15A7|lR?VAuOaY598b-4LA`B?5cjKw$Tyqc#HdKpmqJN@|!CAFozAd@T8#wLd_H zw_({ru{aDQiEHeIJS?=IV@3>mR*rHKkehYgFx;p)LDlf7Qdys;LH+2DmM$o6a;!se zIhbVeJ#ikDAFe#y4BByOLzmR#)ONao2ZN1Klw9fsYsvbeo`QPWB*ys{Zn0aAh`P`yr ze4SOkc~&!t{<8-kW4lIypq&)vt!?n-fPssB=O4dnU?7#`mNs8q>(s224`>cCylqbk zCI9tV^`Cg^*vhqw0w$x>p@407J>Expwslve7?3HbR!@21+Q>3Y32_ngC6aZfGf6Jh z2nyo$t)dp$2SJN_UzD$M*)vRfjJn>qh9->!Nk9=&9+w)+^SV)>}8h z*X$^_ZMr`CwksDr-`mo)zn6Jb2DV$1X~g+oqAG6gW7gNl{scOzvIa<=6Tux4uygFns4REcOW zl>yo5%R4)wz;iI0*r_@p<|}@NI9cv*3K;|`W|(-LX{v@gYNf~8Dpj^ii~o+F_P|EW zbdUFi3nqRJH?AmqEkM?9AL>HnEWzslnU=Z?kL6Dmk4idw&Vh?Z*NcSPpW!s}EgK(4 z{rH8IPj4If-ilm1P8{P}9cps?v*g6ET27csYHS(RuIof!w5&)#lC-@ZoD$j^;s@>1 zR{d$vbc=(vBV@zB@e)uE-}_>*_SZVa?FkDL`)D+W79QS7duFOL$|-7tQV+(?&CM+( zWx&lQDJdzQpj|o{dXH$3S0c(gcJ%X@M#-!Dye8~?#0Rar8oxp86D`{|w<99VQG#)+- z+O0k^cJc)AN~6tlu@!5DgdxID!e(ZVWZ}N0I8(;H02aSj)15OobxWgTgRdhj*mFfN zEMOHby%jaY_hME}hkCooQKvxiWNI%UlT`ctdc42xvCK=vPx@MNmVfYYx2-=rnBtXu zFuLkdUqVo91!{yiO-*|pmi~p*BV==RBOi%v9U0OJ$qkPlb+5kbF;RROW+Z?3g#_9W zld*XVNw14=8i7f8xjdgdk3=XLlCO>bQ9+3@_=pevW}G=0M~za}NQba=f?7J9bs|1r zk~X#Z45IKVQSxr%L|t}vimb(fN;ifYUKnU^T@CIz-DRkOET*L8h4qr^i-;6r^*z=W zDwSjhJS3hagCN27Td3Vdk$jf(3)$m_yJJJDQ2P_MkIxb9;3ORvH|Lnzj9c3g9fVP(IJiK zEVVfVxcrD~6kw*-xC%U}Do<HRT>?s3yw zI1D3zvV)H%%>f-bNfeEj3i@*5aj4C8VCPUQe8VdjIBuRtSOH^)kavE+8Cm4id``wdH<7ToHv^7eMw$o}A`-VD}J zsE^f9p?6>)0zLCHl?3?NA%Vl0`drj!QTjPrRF>FSsdN@6^s~oHI{EQ?dym(;5?JaP zV%`!Bd*;gG-~+%M@$T zFe)0tAaw<*Rb@yo<~&$6=$(OW=a-f?X?i>pMo)j4zj`Q7Iq?a0+y&`NqOX#8DmGF5 zD@@GwCBJFiY%8k=c0DSg3ZDmE#bZ{~GTqe1SLtK;3647(2W_wWb26lH&rUNWWGf{| z(Oj&2vhBG&yojA(`K-rHVwgALb?jJUxRu01kFK<|^!o$r>*j;r4(TY___l*5&8_pLwmG*s;j zl{J)RXexmMKnY3x_tNYf4E6QZo!w#4R?!Mu7`X>+pYIf1KF8N3UP{{w}cJ0IAuFi35 zJ-yIB>vbutsoq3oi`Vux38!@CoLlgiAl$Nx8;$d7U3P*tr01^k3V9$M43;!AYFvCW znp`yVE=|Ep4SXgv@ui0g)(st3!!Ad5uyqcXh#z1Ie3&E_bKr7jP4A1kx>BRobV?8} zM$1flzf#HDw}MLu{0NgGHfcsc;Fi3hxu|f5m{LxImCAEBJZb9$Ekn(0I zaBD7#w6cvC>cgkebG=1mp~vo-vd9VGHD}#h$NWdqfa4X`!GTO8lU;k1(@OPXUzSte6YOBF4%~ju zqndEAO#RcqAb744^vPuGak`D=>5{FT>`apB;@A8XF`^ zXjjWxw%NNq#_I}0Q))+&x^o+|bj@6ws`Pew&A< zw3Pdk3_pD$2r~^5*^bzJLVb7Q1Y${)*P*#!*=cS;W6QgO&Q$kcG1pU@jewoU371eI z1uwH+olmyxccic_*cHLQ#}2p;x;E*agL+^In34iyu`G*qr3+H!*s&s@D;I^bIYx_p zCZxhZ{UQuEpCaXzq^Xs!BUs|L=|4gpFWFG{rutlm{Za&5BpKyu{;jLmR!2FKp66S& zUv^rNI>TK3pe#f-PBOzvJMRe_FRz@~OVH2B5ASPm?IIzqpsVq&c@Xy-P7g zp>T(|Uq4Pf-F!o3ZFj##rA~}Yy+2mJ`cwIAM)}FpRM#H+d>7)}j5X|L5z9BQ^9r>d zrN>Q^wUwbH5%+P&xTJS&Erle?dv(Dc8XFvR;Pyka(%A+_SZn%@M znBWB=leCElF3zJw6537#o*Y4C1(cgS?5Nb;&z|FL@Ic7ATS1+`Fl4i-e= zT6ckWR8RE>XSIswgjJy%ZO-yjc`ZRWljaXx2#n#*X1h~c$s&*|RU^HpvH{lWlHb<6 zI#G$mVuf$+hR-XM#o7PaE`9l~)eyx0`9U_S?`Y{cl*; z4ff=DXYUD)7rm8HDE)-h@ebwC{-h6F*x!y4WYKugQjp4){83o}2MqW&9VY?+YFpzy^PlzoxIY`r!Z=!{KFr4jiyk_# z-W9n#-t4XgjrK9s-Dad3OLuWSKi_N(Wng+H-sGcSTv=4Qc~|XrSW&S-XirkmPm@19 zsobg99L@NGhbKzU{EbzA)n8$y(PH z`)#ry`a7kJ@sXYwkNO7EH=|>k4Oof=HRI8~ypy)3p=7qFmKP@{1}+=dzb>S`TsP6I zU`3X7`_ zWr(Kiwu=ZIf*d?{{dJ0n2l};Tk4#?F7;P zgN&a=DC+!Ot~l|$^4sx+ILf*Tn*Q1BeE;`+L?&jeI~%aS9U0=-A`Rema-!c1ada`6 z>cqP0Zf;2a<4Pa?RR&C@d`e!aDW9K_|mI-7E_21sl@vhMHd zu|?GTv0T%?b-#+>K0h#4?~{8KW+ZcXY+1~&_lG7=pk>~;TVP{vrWb?-4i8m0Fsym^ zhVLfcT%zq)_94*j?>hbD<1;;SM9acfen|whGWibVvHV=GNvaTn{&4&&xjfAqUHtF% z?eSmcgPC$Vi#+TbSNz{9jR@TUG2ixbySpIlKAhd(5E{DwOhuzF3@cWO9IvGMBtdVsSF}~Z3*GP;RCaB6 z{Y$*`#r&~*Eq-=v3-}Rnar6hZq(W-y zqzaX65yfhaY9;m>06bpA=94+hjZMEw5p0u8qJ^5n!l8Pp!d|w6yf^CumD^JLAMS$u-+R|U|Ch<&~?5GE(UEe^t=JaKvY$J*h^b5mAc-b~Q?Y&ID1Ha7;-=KO4SBqPba-Vr`rB5w_RPFA~|PmkP; z%9a?#&Rr_avPv*8x${~Z?oQR#G*&?^wYMQ;YOdVX1rh{F;^$4bW70CnM4mrtb_G|z zjoy<55Rl2K@a-==ww3EcMLQcSaijL9mHyh7DtmGyhc?V+_dT>dw4k)xwE*~evSFdX z4-CSuwNdw#n87y@9tCYpMJCeH+mB0Bq`ef%;P6=39(vPkkg(OOeK%m6uM&M{5%_kY z^qa*??j`2<75)i2-iur!lT}DF$xTI`K(%2hA8&2rFHkGSTeAREThg>HTeJ77*6CBm zb3F(9RnW6PFa&dJ zpk!ipdAX?Tm>vYKH{+5Hy?`%=<5uMo;80aIRzcx48#I;@Sh0B4nVkhp+oT0Uo_H6hgs#8zW z#|yB}%#p71aato`nmH~1A`8wRn62Nq z)p%7##1TioVNcJ>Dc%0d^&nG2=R9%a&_GhV+mgz1NK!99!;`j*&ys7L5rahK+91w-|mxp-^Ce&yc4| zvvw-X`?CVqiGf;i-TleO+=p~F1!U*)ar~N=c9q0eD7;zHZ7Z_*cGmjXm>%YhN!FoH z09=>Ds4n0i>)}ff2-D$YA&|v)#G$}ovIHvG*=yz1cbeje|I6Q3zL$UJ>FfUi51fYG literal 32651 zcma&NWmuNo)-{Yl2!aR*N+aD3(jX$zNOv~~(hUOA-O}CN4N42rE#2K*bbJfE)qC$_ zzt8dc2jPOX&NbJJF~*#yucWvjB0MHM6ciMq(7QKMP*BihP*C^q;qHTfmeH;~Q96ePpMl{b-_TYGwVwght!!!&5poY_P($ zp^Spn@1H~61IyUOCrGOrPx2x=@$9)O91w*H6Q!u160}x4tNK zuEa)ecKUab^+2bCsT&-pDJR*Ec zEmrex`JSILyXiBX>~aql^5=MAvg~Ka)6oG6^xQ^$(?`j>H|%Di>pot5NQXG)1Q3hE z2mXeBu`7#D^V6v#20m^iCB!G3X6>Sf?FBN9+5Vi`gp^vgF@|)dQ^wC*J@h1}-Yk~k zj8KYb9Vx7Ce%2hotfPW48j2dI3g@wba=$@pbWPL)1KUNoWy&cc6_w*BO~sR!P*BdO zLT~tF?9{drV80BvUUc-mWvh({C&5|Ac^diBkBMCCo0m^=ax$6f8+NkoPf73;?o8_+ zKOQ*@r{R)qKk;$5NkczrP84N;LEP|GW$@qwSJ-T)B~;@cRmstL!*#opt9P zA3oGPO!L@R@aYf_{(bOavnPW6e|@M$vX9H{RDIrn4E2fr1%uA%oX3-Y79c>nUEyK# z*e7k0{miCI7^qL&W{qchGBPq+S}&V!H~IJo?*2VEO5{cuZ16lp979GO+nG7Hs zBa>BTJa&6?ZT=W%!r)gwdGH~_@hZ6OG0#;q?CUkLul1*RtWbR9KI+rDVXib9bEP97 zm|xFI5|5;aJl6^H=#Hk%5{)S}ovtk@DH*ok{#mhkv_9lS4A%Pk4Il2|J%TBBUgmE# z-w+#Lj9N6VGn$ zo>A6^$;uNm3H0_L9FdNV>AI8Q9O-B(#Zu$3!mlo>-u9?a$e0@VigUck4=EIQvXkcJ zLiP{ysnlGa!?^7b*R+g%P4jm+o%fc` z6je-r7ux82G1KU*Je`Rtx6`MF=X^B4v0KkSHeRMLAy=r^5rk7=G}0A9@Sx#~Vws-v zPR*)Zp~`m_)jFGPf7-_6=ukCL_SOzOSEuzs;!58NQD?!;(Sr51bR1YD?Cf&Gh5XA2 z0YpmHSN!hczTyEi1*#|;I1>yfv}xTbjvgEOT@k*Ii^^Lnb2XP?1ocO%jq95N>+GCW ztL1M@Szoa)f~PJQxjKiCip8Q~Vb$3muKY5!N6&ra`?tmxT|j=A`%|W+>uLglPs0wz z4Sq}ETE!$!uE0Qgf1xeXd2=LBkeIf9@4hl*ofhJVn%T#BdlfB43t~5)zzs?hOs8cC zM^Z>8^R{w5$yaNLz4k8`zL^Un7Aa+o%9Y7!hUw5gc{n}FX0eov8&$CKJ)Bg(H-1U9 zvR1PNW|`M$T&_oL#17J*!fz5;5zpmlqeLTW`X6AI6I{ zO;Fhax5bMX9ea|Tj}?PE7G)d0u!U>np^}JdaKyf%TvR=xnVoyQt}{+EjCs{DlrGdF zH?sQms(WoECAO=lSg!}Oa-?-Y(Rl}xd6K^IqetEJ+#0+D&lOXJ5N%t&Vp%7S+f{AQ zni$k4k#D@EUt@fpV0v`Cbmujtt@OjEGx6YsF&;|t&!~$ikm?o9)9*{v^-6s>zM0e% zk*2_TsDlXNC(rlfu#ZQAIEF#@XPN#J%85p24&`jQ0;M-$9W*M{ym@JF1GP@R)!QG| zpX~U$LnEjG2kPUwktxD`_3=}|@#fg>jQNhohmkE==fahqxM(@pC%8X?UX!FZWr-)e zR3ErMU6=n8n0{n;jmcy@q;jPaCo6YwqYAl=}Ic5)vT1ZZ>vROl$Tn@8? zxq;?#SL9Qn;Lo2wKUBK9I+;~8-rDprVROB{91BnGjg_O6%kRXbHR_@wnpQnV`dvRusLP15F zJ~I!Ysw2RY3EsLRXDe*rjP`&(zT~+7_DipqMj#jDrC>Z{sP-t8ZSdDMYjrwXjxN6( zlHd^_nl6zU`Y$W8I*#S)c1PXF)(YzAq&uKazu20cNE3Xr+u)dLy*WBV^dwuJ3-^ig z_IOEJZo`d+GQ>f4aReA_$Ou@tJrGL}LABN@rKwD>$KiNFpD?Tu(wd9IVYAh6GDBF# zb-CA)@9C3%fNeIbaLLZs~!WsCuITb2{7)RB(-&Ws-+4UIv) zQEl>xk$Jb?)=)Qnx&|*8gq;H{Li1TY+}=eP<

@OZmh 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 "-taxCalculator" TaxCalculator -DomesticTax ..|> TaxCalculator -ForeignTax ..|> TaxCalculator +DomesticTaxCalculator ..|> TaxCalculator +ForeignTaxCalculator ..|> TaxCalculator @enduml \ No newline at end of file diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java index 67eeec054..1951e738b 100644 --- a/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java +++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java @@ -24,8 +24,8 @@ package com.iluwatar.separatedinterface; import com.iluwatar.separatedinterface.invoice.InvoiceGenerator; -import com.iluwatar.separatedinterface.taxes.DomesticTax; -import com.iluwatar.separatedinterface.taxes.ForeignTax; +import com.iluwatar.separatedinterface.taxes.DomesticTaxCalculator; +import com.iluwatar.separatedinterface.taxes.ForeignTaxCalculator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,11 +51,12 @@ public class App { */ public static void main(String[] args) { //Create the invoice generator with product cost as 50 and foreign product tax - var internationalProductInvoice = new InvoiceGenerator(PRODUCT_COST, new ForeignTax()); + var internationalProductInvoice = new InvoiceGenerator(PRODUCT_COST, + new ForeignTaxCalculator()); LOGGER.info("Foreign Tax applied: {}", "" + internationalProductInvoice.getAmountWithTax()); //Create the invoice generator with product cost as 50 and domestic product tax - var domesticProductInvoice = new InvoiceGenerator(PRODUCT_COST, new DomesticTax()); + var domesticProductInvoice = new InvoiceGenerator(PRODUCT_COST, new DomesticTaxCalculator()); LOGGER.info("Domestic Tax applied: {}", "" + domesticProductInvoice.getAmountWithTax()); } } diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTax.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculator.java similarity index 95% rename from separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTax.java rename to separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculator.java index ebe0e306e..788afb90a 100644 --- a/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTax.java +++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculator.java @@ -28,7 +28,7 @@ import com.iluwatar.separatedinterface.invoice.TaxCalculator; /** * TaxCalculator for Domestic goods with 20% tax. */ -public class DomesticTax implements TaxCalculator { +public class DomesticTaxCalculator implements TaxCalculator { public static final double TAX_PERCENTAGE = 20; diff --git a/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTax.java b/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculator.java similarity index 96% rename from separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTax.java rename to separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculator.java index 583f70d3b..c2b12e2f5 100644 --- a/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTax.java +++ b/separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculator.java @@ -28,7 +28,7 @@ import com.iluwatar.separatedinterface.invoice.TaxCalculator; /** * TaxCalculator for foreign goods with 60% tax. */ -public class ForeignTax implements TaxCalculator { +public class ForeignTaxCalculator implements TaxCalculator { public static final double TAX_PERCENTAGE = 60; diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculatorTest.java similarity index 89% rename from separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxTest.java rename to separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculatorTest.java index d070d8b0a..dac3ec2d6 100644 --- a/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxTest.java +++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculatorTest.java @@ -26,13 +26,13 @@ package com.iluwatar.separatedinterface.taxes; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class DomesticTaxTest { +public class DomesticTaxCalculatorTest { - private DomesticTax target; + private DomesticTaxCalculator target; @Test - public void testTaxCaluclation(){ - target = new DomesticTax(); + public void testTaxCalculation(){ + target = new DomesticTaxCalculator(); var tax=target.calculate(100.0); Assertions.assertEquals(tax,20.0); diff --git a/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxTest.java b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculatorTest.java similarity index 89% rename from separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxTest.java rename to separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculatorTest.java index df184276c..22526b6df 100644 --- a/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxTest.java +++ b/separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculatorTest.java @@ -26,13 +26,13 @@ package com.iluwatar.separatedinterface.taxes; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class ForeignTaxTest { +public class ForeignTaxCalculatorTest { - private ForeignTax target; + private ForeignTaxCalculator target; @Test - public void testTaxCaluclation(){ - target = new ForeignTax(); + public void testTaxCalculation(){ + target = new ForeignTaxCalculator(); var tax=target.calculate(100.0); Assertions.assertEquals(tax,60.0);