Compare commits
29 Commits
all-contri
...
all-contri
Author | SHA1 | Date | |
---|---|---|---|
|
578b3528d5 | ||
|
5674f3c52e | ||
|
4ad2bfefad | ||
|
e5d219609d | ||
|
21ca47a22e | ||
|
ebd38bcfaa | ||
|
a125879d15 | ||
|
d2e070d21d | ||
|
82eb41b641 | ||
|
24e8fa1bad | ||
|
9017975276 | ||
|
87093cf221 | ||
|
6cb5b4a683 | ||
|
e6ddff5f25 | ||
|
b5fddd469a | ||
|
9cbc509c3a | ||
|
9c648cbdb8 | ||
|
e6cca86e25 | ||
|
c204b242df | ||
|
2e98dcf217 | ||
|
9d44eea64f | ||
|
6f592f5e8a | ||
|
74b968942f | ||
|
ebc0e8b3cd | ||
|
9088ac51f6 | ||
|
c8f7a8f0e6 | ||
|
a2967c5a40 | ||
|
7fd7735527 | ||
|
f6942cf18d |
@@ -1204,6 +1204,24 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "swarajsaaj",
|
||||
"name": "Swaraj",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/6285049?v=4",
|
||||
"profile": "https://github.com/swarajsaaj",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ChFlick",
|
||||
"name": "Christoph Flick",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/4465376?v=4",
|
||||
"profile": "http://christophflick.de",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 4,
|
||||
|
@@ -10,7 +10,7 @@
|
||||
[](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
|
||||
[](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
# Introduction
|
||||
@@ -267,6 +267,10 @@ This project is licensed under the terms of the MIT license.
|
||||
<td align="center"><a href="https://github.com/samilAyoub"><img src="https://avatars0.githubusercontent.com/u/61546990?v=4" width="100px;" alt=""/><br /><sub><b>samilAyoub</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=samilAyoub" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/vdlald"><img src="https://avatars0.githubusercontent.com/u/29997701?v=4" width="100px;" alt=""/><br /><sub><b>Vladislav Golubinov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=vdlald" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/swarajsaaj"><img src="https://avatars2.githubusercontent.com/u/6285049?v=4" width="100px;" alt=""/><br /><sub><b>Swaraj</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=swarajsaaj" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://christophflick.de"><img src="https://avatars0.githubusercontent.com/u/4465376?v=4" width="100px;" alt=""/><br /><sub><b>Christoph Flick</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ChFlick" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-enable -->
|
||||
|
@@ -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.abstractfactory;
|
||||
|
||||
public class Kingdom {
|
||||
|
@@ -24,11 +24,11 @@ Use the Event Sourcing pattern when
|
||||
|
||||
## Real world examples
|
||||
|
||||
* [The Lmax Architecture] (https://martinfowler.com/articles/lmax.html)
|
||||
* [The Lmax Architecture](https://martinfowler.com/articles/lmax.html)
|
||||
|
||||
## Credits
|
||||
|
||||
* [Martin Fowler - Event Sourcing] (https://martinfowler.com/eaaDev/EventSourcing.html)
|
||||
* [Event Sourcing | Microsoft Docs] (https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing)
|
||||
* [Reference 3: Introducing Event Sourcing] (https://msdn.microsoft.com/en-us/library/jj591559.aspx)
|
||||
* [Martin Fowler - Event Sourcing](https://martinfowler.com/eaaDev/EventSourcing.html)
|
||||
* [Event Sourcing | Microsoft Docs](https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing)
|
||||
* [Reference 3: Introducing Event Sourcing](https://msdn.microsoft.com/en-us/library/jj591559.aspx)
|
||||
* [Event Sourcing pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing)
|
||||
|
@@ -1,3 +1,27 @@
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
@@ -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.factory;
|
||||
|
||||
/**
|
||||
|
@@ -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.factory;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
@@ -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.factory;
|
||||
|
||||
/**
|
||||
|
@@ -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.factory;
|
||||
|
||||
/**
|
||||
|
@@ -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.factory;
|
||||
|
||||
/**
|
||||
|
@@ -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.factory;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
@@ -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.factory;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
@@ -9,6 +9,10 @@ tags:
|
||||
- Performance
|
||||
---
|
||||
|
||||
## Also known as
|
||||
|
||||
Resource Pool
|
||||
|
||||
## Intent
|
||||
|
||||
When objects are expensive to create and they are needed only for short periods of time it is
|
||||
|
1
pom.xml
@@ -196,6 +196,7 @@
|
||||
<module>transaction-script</module>
|
||||
<module>filterer</module>
|
||||
<module>factory</module>
|
||||
<module>separated-interface</module>
|
||||
</modules>
|
||||
|
||||
<repositories>
|
||||
|
138
separated-interface/README.md
Normal file
@@ -0,0 +1,138 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Separated Interface
|
||||
folder: separated-interface
|
||||
permalink: /patterns/separated-interface/
|
||||
categories: Structural
|
||||
tags:
|
||||
- Decoupling
|
||||
---
|
||||
|
||||
|
||||
## Intent
|
||||
|
||||
Separate the interface definition and implementation in different packages. This allows the client
|
||||
to be completely 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 ([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**
|
||||
|
||||
**Client**
|
||||
|
||||
`InvoiceGenerator` 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. `ForeignTaxCalculator` is one of them which levies 60% tax
|
||||
for international products.
|
||||
|
||||
```java
|
||||
public class ForeignTaxCalculator implements TaxCalculator {
|
||||
|
||||
public static final double TAX_PERCENTAGE = 60;
|
||||
|
||||
@Override
|
||||
public double calculate(double amount) {
|
||||
return amount * TAX_PERCENTAGE / 100.0;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Another is `DomesticTaxCalculator` which levies 20% tax for international products.
|
||||
|
||||
```java
|
||||
public class DomesticTaxCalculator 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 ForeignTaxCalculator());
|
||||
|
||||
LOGGER.info("Foreign Tax applied: {}", "" + internationalProductInvoice.getAmountWithTax());
|
||||
|
||||
var domesticProductInvoice = new InvoiceGenerator(PRODUCT_COST, new DomesticTaxCalculator());
|
||||
|
||||
LOGGER.info("Domestic Tax applied: {}", "" + domesticProductInvoice.getAmountWithTax());
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||
|
||||
## 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)
|
||||
* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0321127420&linkId=e08dfb7f2cf6153542ef1b5a00b10abc)
|
BIN
separated-interface/etc/class_diagram.png
Normal file
After Width: | Height: | Size: 32 KiB |
36
separated-interface/etc/separated-interface.urm.puml
Normal file
@@ -0,0 +1,36 @@
|
||||
@startuml
|
||||
package com.iluwatar.separatedinterface {
|
||||
class App {
|
||||
- LOGGER : Logger {static}
|
||||
+ PRODUCT_COST : double {static}
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
}
|
||||
package com.iluwatar.separatedinterface.taxes {
|
||||
class DomesticTaxCalculator {
|
||||
+ TAX_PERCENTAGE : double {static}
|
||||
+ DomesticTaxCalculator()
|
||||
+ calculate(amount : double) : double
|
||||
}
|
||||
class ForeignTaxCalculator {
|
||||
+ TAX_PERCENTAGE : double {static}
|
||||
+ ForeignTaxCalculator()
|
||||
+ calculate(amount : double) : double
|
||||
}
|
||||
}
|
||||
package com.iluwatar.separatedinterface.invoice {
|
||||
class InvoiceGenerator {
|
||||
- amount : double
|
||||
- taxCalculator : TaxCalculator
|
||||
+ InvoiceGenerator(amount : double, taxCalculator : TaxCalculator)
|
||||
+ getAmountWithTax() : double
|
||||
}
|
||||
interface TaxCalculator {
|
||||
+ calculate(double) : double {abstract}
|
||||
}
|
||||
}
|
||||
InvoiceGenerator --> "-taxCalculator" TaxCalculator
|
||||
DomesticTaxCalculator ..|> TaxCalculator
|
||||
ForeignTaxCalculator ..|> TaxCalculator
|
||||
@enduml
|
71
separated-interface/pom.xml
Normal file
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.24.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>separated-interface</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.iluwatar.separatedinterface.App</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.DomesticTaxCalculator;
|
||||
import com.iluwatar.separatedinterface.taxes.ForeignTaxCalculator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>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.</p>
|
||||
*
|
||||
* <p>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.</p>
|
||||
*/
|
||||
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 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 DomesticTaxCalculator());
|
||||
LOGGER.info("Domestic Tax applied: {}", "" + domesticProductInvoice.getAmountWithTax());
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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}).
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
|
||||
}
|
@@ -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 DomesticTaxCalculator implements TaxCalculator {
|
||||
|
||||
public static final double TAX_PERCENTAGE = 20;
|
||||
|
||||
@Override
|
||||
public double calculate(double amount) {
|
||||
return amount * TAX_PERCENTAGE / 100.0;
|
||||
}
|
||||
|
||||
}
|
@@ -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 ForeignTaxCalculator implements TaxCalculator {
|
||||
|
||||
public static final double TAX_PERCENTAGE = 60;
|
||||
|
||||
@Override
|
||||
public double calculate(double amount) {
|
||||
return amount * TAX_PERCENTAGE / 100.0;
|
||||
}
|
||||
|
||||
}
|
@@ -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[]{}));
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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;
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
@@ -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.taxes;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class DomesticTaxCalculatorTest {
|
||||
|
||||
private DomesticTaxCalculator target;
|
||||
|
||||
@Test
|
||||
public void testTaxCalculation(){
|
||||
target = new DomesticTaxCalculator();
|
||||
|
||||
var tax=target.calculate(100.0);
|
||||
Assertions.assertEquals(tax,20.0);
|
||||
}
|
||||
|
||||
}
|
@@ -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.taxes;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ForeignTaxCalculatorTest {
|
||||
|
||||
private ForeignTaxCalculator target;
|
||||
|
||||
@Test
|
||||
public void testTaxCalculation(){
|
||||
target = new ForeignTaxCalculator();
|
||||
|
||||
var tax=target.calculate(100.0);
|
||||
Assertions.assertEquals(tax,60.0);
|
||||
}
|
||||
|
||||
}
|
@@ -9,14 +9,16 @@ tags:
|
||||
---
|
||||
|
||||
## Intent
|
||||
Ensure a class only has one instance, and provide a global point of
|
||||
access to it.
|
||||
|
||||
Ensure a class only has one instance, and provide a global point of access to it.
|
||||
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
|
||||
> There can only be one ivory tower where the wizards study their magic. The same enchanted ivory tower is always used by the wizards. Ivory tower here is singleton.
|
||||
> There can only be one ivory tower where the wizards study their magic. The same enchanted ivory
|
||||
> tower is always used by the wizards. Ivory tower here is singleton.
|
||||
|
||||
In plain words
|
||||
|
||||
@@ -24,7 +26,9 @@ In plain words
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system.
|
||||
> In software engineering, the singleton pattern is a software design pattern that restricts the
|
||||
> instantiation of a class to one object. This is useful when exactly one object is needed to
|
||||
> coordinate actions across the system.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
@@ -38,7 +42,7 @@ public enum EnumIvoryTower {
|
||||
}
|
||||
```
|
||||
|
||||
Then in order to use
|
||||
Then in order to use:
|
||||
|
||||
```java
|
||||
var enumIvoryTower1 = EnumIvoryTower.INSTANCE;
|
||||
@@ -47,9 +51,11 @@ assertEquals(enumIvoryTower1, enumIvoryTower2); // true
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Singleton pattern when
|
||||
|
||||
* There must be exactly one instance of a class, and it must be accessible to clients from a well-known access point
|
||||
|
@@ -10,12 +10,17 @@ tags:
|
||||
---
|
||||
|
||||
## Intent
|
||||
As explained in the book [Game Programming Patterns](http://gameprogrammingpatterns.com/spatial-partition.html) by Bob Nystrom, spatial partition pattern helps to
|
||||
|
||||
> efficiently locate objects by storing them in a data structure organized by their positions.
|
||||
As explained in the book [Game Programming Patterns](http://gameprogrammingpatterns.com/spatial-partition.html)
|
||||
by Bob Nystrom, spatial partition pattern helps to efficiently locate objects by storing them in a
|
||||
data structure organized by their positions.
|
||||
|
||||
## Explanation
|
||||
Say, you are building a war game with hundreds, or maybe even thousands of players, who are clashing on the battle field. Each player's position is getting updated every frame. The simple way to handle all interactions taking place on the field is to check each player's position against every other player's position:
|
||||
|
||||
Say, you are building a war game with hundreds, or maybe even thousands of players, who are clashing
|
||||
on the battle field. Each player's position is getting updated every frame. The simple way to handle
|
||||
all interactions taking place on the field is to check each player's position against every other
|
||||
player's position:
|
||||
|
||||
```java
|
||||
public void handleMeLee(Unit units[], int numUnits) {
|
||||
@@ -32,21 +37,33 @@ public void handleMeLee(Unit units[], int numUnits) {
|
||||
}
|
||||
```
|
||||
|
||||
This will include a lot of unnecessary checks between players which are too far apart to have any influence on each other. The nested loops gives this operation an O(n^2) complexity, which has to be performed every frame since many of the objects on the field may be moving each frame.
|
||||
The idea behind the Spatial Partition design pattern is to enable quick location of objects using a data structure that is organised by their positions, so when performing an operation like the one above, every object's position need not be checked against all other objects' positions. The data structure can be used to store moving and static objects, though in order to keep track of the moving objects, their positions will have to be reset each time they move. This would mean having to create a new instance of the data structure each time an object moves, which would use up additional memory. The common data structures used for this design pattern are:
|
||||
This will include a lot of unnecessary checks between players which are too far apart to have any
|
||||
influence on each other. The nested loops gives this operation an O(n^2) complexity, which has to be
|
||||
performed every frame since many of the objects on the field may be moving each frame. The idea
|
||||
behind the Spatial Partition design pattern is to enable quick location of objects using a data
|
||||
structure that is organised by their positions, so when performing an operation like the one above,
|
||||
every object's position need not be checked against all other objects' positions. The data structure
|
||||
can be used to store moving and static objects, though in order to keep track of the moving objects,
|
||||
their positions will have to be reset each time they move. This would mean having to create a new
|
||||
instance of the data structure each time an object moves, which would use up additional memory. The
|
||||
common data structures used for this design pattern are:
|
||||
|
||||
* Grid
|
||||
* Quad tree
|
||||
* k-d tree
|
||||
* K-d tree
|
||||
* BSP
|
||||
* Boundary volume hierarchy
|
||||
|
||||
In our implementation, we use the Quadtree data structure which will reduce the time complexity of finding the objects within a certain range from O(n^2) to O(nlogn), decreasing the computations required significantly in case of large number of objects.
|
||||
In our implementation, we use the Quadtree data structure which will reduce the time complexity of
|
||||
finding the objects within a certain range from O(n^2) to O(nlogn), decreasing the computations
|
||||
required significantly in case of large number of objects.
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
This pattern can be used:
|
||||
|
||||
* When you need to keep track of a large number of objects' positions, which are getting updated every frame.
|
||||
|
@@ -24,7 +24,6 @@
|
||||
package com.iluwatar.spatialpartition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
|
@@ -9,36 +9,46 @@ tags:
|
||||
---
|
||||
|
||||
## Also known as
|
||||
|
||||
Filter, Criteria
|
||||
|
||||
## Intent
|
||||
Specification pattern separates the statement of how to match a
|
||||
candidate, from the candidate object that it is matched against. As well as its
|
||||
usefulness in selection, it is also valuable for validation and for building to
|
||||
order.
|
||||
|
||||
Specification pattern separates the statement of how to match a candidate, from the candidate object
|
||||
that it is matched against. As well as its usefulness in selection, it is also valuable for
|
||||
validation and for building to order.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
|
||||
> There is a pool of different creatures and we often need to select some subset of them.
|
||||
> We can write our search specification such as "creatures that can fly", "creatures heavier than 500 kilograms", or as a combination of other search specifications, and then give it to the party that will perform the filtering.
|
||||
> There is a pool of different creatures and we often need to select some subset of them. We can
|
||||
> write our search specification such as "creatures that can fly", "creatures heavier than 500
|
||||
> kilograms", or as a combination of other search specifications, and then give it to the party that
|
||||
> will perform the filtering.
|
||||
|
||||
In Plain Words
|
||||
|
||||
> Specification pattern allows us to separate the search criteria from the object that performs the search.
|
||||
> Specification pattern allows us to separate the search criteria from the object that performs the
|
||||
> search.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> In computer programming, the specification pattern is a particular software design pattern, whereby business rules can be recombined by chaining the business rules together using boolean logic.
|
||||
> In computer programming, the specification pattern is a particular software design pattern,
|
||||
> whereby business rules can be recombined by chaining the business rules together using boolean
|
||||
> logic.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
If we look at our creature pool example from above, we have a set of creatures with certain properties.
|
||||
Those properties can be part of a pre-defined, limited set (represented here by the enums Size, Movement and Color); but they can also be continuous values (e.g. the mass of a Creature).
|
||||
In this case, it is more appropriate to use what we call "parameterized specification", where the property value can be given as an argument when the Creature is instantiated, allowing for more flexibility.
|
||||
A third option is to combine pre-defined and/or parameterized properties using boolean logic, allowing for near-endless selection possibilities (this is called "composite specification", see below).
|
||||
The pros and cons of each approach are detailed in the table at the end of this document.
|
||||
If we look at our creature pool example from above, we have a set of creatures with certain
|
||||
properties. Those properties can be part of a pre-defined, limited set (represented here by the
|
||||
enums Size, Movement and Color); but they can also be continuous values (e.g. the mass of a
|
||||
Creature). In this case, it is more appropriate to use what we call "parameterized specification",
|
||||
where the property value can be given as an argument when the Creature is instantiated, allowing for
|
||||
more flexibility. A third option is to combine pre-defined and/or parameterized properties using
|
||||
boolean logic, allowing for near-endless selection possibilities (this is called "composite
|
||||
specification", see below). The pros and cons of each approach are detailed in the table at the end
|
||||
of this document.
|
||||
|
||||
```java
|
||||
public interface Creature {
|
||||
@@ -50,7 +60,7 @@ public interface Creature {
|
||||
}
|
||||
```
|
||||
|
||||
And ``Dragon`` implementation looks like this.
|
||||
And `Dragon` implementation looks like this.
|
||||
|
||||
```java
|
||||
public class Dragon extends AbstractCreature {
|
||||
@@ -61,7 +71,8 @@ public class Dragon extends AbstractCreature {
|
||||
}
|
||||
```
|
||||
|
||||
Now that we want to select some subset of them, we use selectors. To select creatures that fly, we should use ``MovementSelector``.
|
||||
Now that we want to select some subset of them, we use selectors. To select creatures that fly, we
|
||||
should use `MovementSelector`.
|
||||
|
||||
```java
|
||||
public class MovementSelector extends AbstractSelector<Creature> {
|
||||
@@ -79,7 +90,8 @@ public class MovementSelector extends AbstractSelector<Creature> {
|
||||
}
|
||||
```
|
||||
|
||||
On the other hand, when selecting creatures heavier than a chosen amount, we use ``MassGreaterThanSelector``.
|
||||
On the other hand, when selecting creatures heavier than a chosen amount, we use
|
||||
`MassGreaterThanSelector`.
|
||||
|
||||
```java
|
||||
public class MassGreaterThanSelector extends AbstractSelector<Creature> {
|
||||
@@ -111,7 +123,8 @@ But we could also use our parameterized selector like this:
|
||||
.collect(Collectors.toList());
|
||||
```
|
||||
|
||||
Our third option is to combine multiple selectors together. Performing a search for special creatures (defined as red, flying, and not small) could be done as follows:
|
||||
Our third option is to combine multiple selectors together. Performing a search for special
|
||||
creatures (defined as red, flying, and not small) could be done as follows:
|
||||
|
||||
```java
|
||||
var specialCreaturesSelector =
|
||||
@@ -123,8 +136,9 @@ Our third option is to combine multiple selectors together. Performing a search
|
||||
|
||||
**More on Composite Specification**
|
||||
|
||||
In Composite Specification, we will create custom instances of ``AbstractSelector`` by combining other selectors (called "leaves") using the three basic logical operators.
|
||||
These are implemented in ``ConjunctionSelector``, ``DisjunctionSelector`` and ``NegationSelector``.
|
||||
In Composite Specification, we will create custom instances of `AbstractSelector` by combining
|
||||
other selectors (called "leaves") using the three basic logical operators. These are implemented in
|
||||
`ConjunctionSelector`, `DisjunctionSelector` and `NegationSelector`.
|
||||
|
||||
```java
|
||||
public abstract class AbstractSelector<T> implements Predicate<T> {
|
||||
@@ -163,12 +177,14 @@ public class ConjunctionSelector<T> extends AbstractSelector<T> {
|
||||
}
|
||||
```
|
||||
|
||||
All that is left to do is now to create leaf selectors (be it hard-coded or parameterized ones) that are as generic as possible,
|
||||
and we will be able to instantiate the ``AbstractSelector`` class by combining any amount of selectors, as exemplified above.
|
||||
We should be careful though, as it is easy to make a mistake when combining many logical operators; in particular, we should pay attention to the priority of the operations.\
|
||||
In general, Composite Specification is a great way to write more reusable code, as there is no need to create a Selector class for each filtering operation.
|
||||
Instead, we just create an instance of ``AbstractSelector`` "on the spot", using tour generic "leaf" selectors and some basic boolean logic.
|
||||
|
||||
All that is left to do is now to create leaf selectors (be it hard-coded or parameterized ones) that
|
||||
are as generic as possible, and we will be able to instantiate the ``AbstractSelector`` class by
|
||||
combining any amount of selectors, as exemplified above. We should be careful though, as it is easy
|
||||
to make a mistake when combining many logical operators; in particular, we should pay attention to
|
||||
the priority of the operations. In general, Composite Specification is a great way to write more
|
||||
reusable code, as there is no need to create a Selector class for each filtering operation. Instead,
|
||||
we just create an instance of ``AbstractSelector`` "on the spot", using tour generic "leaf"
|
||||
selectors and some basic boolean logic.
|
||||
|
||||
**Comparison of the different approaches**
|
||||
|
||||
@@ -181,9 +197,11 @@ Instead, we just create an instance of ``AbstractSelector`` "on the spot", using
|
||||
| | | + Supports logical operations | - You still need to create the base classes used as leaves |
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Specification pattern when
|
||||
|
||||
* You need to select a subset of objects based on some criteria, and to refresh the selection at various times.
|
||||
|
@@ -9,15 +9,21 @@ tags:
|
||||
---
|
||||
|
||||
## Also known as
|
||||
|
||||
Objects for States
|
||||
|
||||
## Intent
|
||||
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
|
||||
|
||||
Allow an object to alter its behavior when its internal state changes. The object will appear to
|
||||
change its class.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
|
||||
> When observing a mammoth in its natural habitat it seems to change its behavior based on the situation. It may first appear calm but over time when it detects a threat it gets angry and dangerous to its surroundings.
|
||||
> When observing a mammoth in its natural habitat it seems to change its behavior based on the
|
||||
> situation. It may first appear calm but over time when it detects a threat it gets angry and
|
||||
> dangerous to its surroundings.
|
||||
|
||||
In plain words
|
||||
|
||||
@@ -25,7 +31,10 @@ In plain words
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> The state pattern is a behavioral software design pattern that allows an object to alter its behavior when its internal state changes. This pattern is close to the concept of finite-state machines. The state pattern can be interpreted as a strategy pattern, which is able to switch a strategy through invocations of methods defined in the pattern's interface.
|
||||
> The state pattern is a behavioral software design pattern that allows an object to alter its
|
||||
> behavior when its internal state changes. This pattern is close to the concept of finite-state
|
||||
> machines. The state pattern can be interpreted as a strategy pattern, which is able to switch a
|
||||
> strategy through invocations of methods defined in the pattern's interface.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
@@ -126,17 +135,23 @@ And here is the full example how the mammoth behaves over time.
|
||||
mammoth.observe();
|
||||
mammoth.timePasses();
|
||||
mammoth.observe();
|
||||
|
||||
// The mammoth gets angry!
|
||||
// The mammoth is furious!
|
||||
// The mammoth calms down.
|
||||
// The mammoth is calm and peaceful.
|
||||
```
|
||||
|
||||
Program output:
|
||||
|
||||
```java
|
||||
The mammoth gets angry!
|
||||
The mammoth is furious!
|
||||
The mammoth calms down.
|
||||
The mammoth is calm and peaceful.
|
||||
```
|
||||
|
||||
## Class diagram
|
||||

|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
Use the State pattern in either of the following cases
|
||||
|
||||
* An object's behavior depends on its state, and it must change its behavior at run-time depending on that state
|
||||
|
Before Width: | Height: | Size: 17 KiB |
@@ -1,80 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
|
||||
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
|
||||
<class id="1" language="java" name="com.iluwatar.state.AngryState" project="state"
|
||||
file="/state/src/main/java/com/iluwatar/state/AngryState.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="124" width="157" x="98" y="310"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="2" language="java" name="com.iluwatar.state.PeacefulState" project="state"
|
||||
file="/state/src/main/java/com/iluwatar/state/PeacefulState.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="124" width="173" x="295" y="310"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<interface id="3" language="java" name="com.iluwatar.state.State" project="state"
|
||||
file="/state/src/main/java/com/iluwatar/state/State.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="106" width="136" x="138" y="674"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<class id="4" language="java" name="com.iluwatar.state.Mammoth" project="state"
|
||||
file="/state/src/main/java/com/iluwatar/state/Mammoth.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="160" width="177" x="138" y="474"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<realization id="5">
|
||||
<bendpoint x="107" y="474"/>
|
||||
<end type="SOURCE" refId="1"/>
|
||||
<end type="TARGET" refId="3"/>
|
||||
</realization>
|
||||
<association id="6">
|
||||
<end type="SOURCE" refId="4" navigable="false">
|
||||
<attribute id="7" name="state"/>
|
||||
<multiplicity id="8" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="3" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<realization id="9">
|
||||
<bendpoint x="345" y="474"/>
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="3"/>
|
||||
</realization>
|
||||
<association id="10">
|
||||
<end type="SOURCE" refId="1" navigable="false">
|
||||
<attribute id="11" name="mammoth"/>
|
||||
<multiplicity id="12" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="4" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="13">
|
||||
<end type="SOURCE" refId="2" navigable="false">
|
||||
<attribute id="14" name="mammoth"/>
|
||||
<multiplicity id="15" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="4" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</classifier-display>
|
||||
<association-display labels="true" multiplicity="true"/>
|
||||
</class-diagram>
|
Before Width: | Height: | Size: 33 KiB |
BIN
state/etc/state_urm.png
Normal file
After Width: | Height: | Size: 34 KiB |
@@ -9,17 +9,20 @@ tags:
|
||||
---
|
||||
|
||||
## Also known as
|
||||
|
||||
Policy
|
||||
|
||||
## Intent
|
||||
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary
|
||||
independently from clients that use it.
|
||||
|
||||
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets
|
||||
the algorithm vary independently from clients that use it.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
|
||||
> Slaying dragons is a dangerous profession. With experience it becomes easier. Veteran dragonslayers have developed different fighting strategies against different types of dragons.
|
||||
> Slaying dragons is a dangerous job. With experience it becomes easier. Veteran
|
||||
> dragonslayers have developed different fighting strategies against different types of dragons.
|
||||
|
||||
In plain words
|
||||
|
||||
@@ -27,7 +30,8 @@ In plain words
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral software design pattern that enables selecting an algorithm at runtime.
|
||||
> In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral
|
||||
> software design pattern that enables selecting an algorithm at runtime.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
@@ -71,7 +75,8 @@ public class SpellStrategy implements DragonSlayingStrategy {
|
||||
}
|
||||
```
|
||||
|
||||
And here is the mighty dragonslayer who is able to pick his fighting strategy based on the opponent.
|
||||
And here is the mighty dragonslayer, who is able to pick his fighting strategy based on the
|
||||
opponent.
|
||||
|
||||
```java
|
||||
public class DragonSlayer {
|
||||
@@ -92,7 +97,7 @@ public class DragonSlayer {
|
||||
}
|
||||
```
|
||||
|
||||
Finally here's dragonslayer in action.
|
||||
Finally here's the dragonslayer in action.
|
||||
|
||||
```java
|
||||
LOGGER.info("Green dragon spotted ahead!");
|
||||
@@ -104,19 +109,25 @@ Finally here's dragonslayer in action.
|
||||
LOGGER.info("Black dragon lands before you.");
|
||||
dragonSlayer.changeStrategy(new SpellStrategy());
|
||||
dragonSlayer.goToBattle();
|
||||
|
||||
// Green dragon spotted ahead!
|
||||
// With your Excalibur you sever the dragon's head!
|
||||
// Red dragon emerges.
|
||||
// You shoot the dragon with the magical crossbow and it falls dead on the ground!
|
||||
// Black dragon lands before you.
|
||||
// You cast the spell of disintegration and the dragon vaporizes in a pile of dust!
|
||||
```
|
||||
|
||||
Program output:
|
||||
|
||||
```
|
||||
Green dragon spotted ahead!
|
||||
With your Excalibur you sever the dragon's head!
|
||||
Red dragon emerges.
|
||||
You shoot the dragon with the magical crossbow and it falls dead on the ground!
|
||||
Black dragon lands before you.
|
||||
You cast the spell of disintegration and the dragon vaporizes in a pile of dust!
|
||||
```
|
||||
|
||||
## Class diagram
|
||||

|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Strategy pattern when
|
||||
|
||||
* Many related classes differ only in their behavior. Strategies provide a way to configure a class either one of many behaviors
|
||||
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,75 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
|
||||
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
|
||||
<interface id="1" language="java" name="com.iluwatar.strategy.DragonSlayingStrategy" project="strategy"
|
||||
file="/strategy/src/main/java/com/iluwatar/strategy/DragonSlayingStrategy.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="88" width="186" x="525" y="428"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<class id="2" language="java" name="com.iluwatar.strategy.ProjectileStrategy" project="strategy"
|
||||
file="/strategy/src/main/java/com/iluwatar/strategy/ProjectileStrategy.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="106" width="151" x="218" y="264"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="3" language="java" name="com.iluwatar.strategy.SpellStrategy" project="strategy"
|
||||
file="/strategy/src/main/java/com/iluwatar/strategy/SpellStrategy.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="106" width="125" x="409" y="264"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="4" language="java" name="com.iluwatar.strategy.DragonSlayer" project="strategy"
|
||||
file="/strategy/src/main/java/com/iluwatar/strategy/DragonSlayer.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="124" width="284" x="574" y="264"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="5" language="java" name="com.iluwatar.strategy.MeleeStrategy" project="strategy"
|
||||
file="/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="106" width="127" x="898" y="264"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<realization id="6">
|
||||
<end type="SOURCE" refId="5"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</realization>
|
||||
<realization id="7">
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</realization>
|
||||
<realization id="8">
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</realization>
|
||||
<association id="9">
|
||||
<end type="SOURCE" refId="4" navigable="false">
|
||||
<attribute id="10" name="strategy"/>
|
||||
<multiplicity id="11" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="1" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</classifier-display>
|
||||
<association-display labels="true" multiplicity="true"/>
|
||||
</class-diagram>
|
Before Width: | Height: | Size: 28 KiB |
BIN
strategy/etc/strategy_urm.png
Normal file
After Width: | Height: | Size: 29 KiB |
@@ -9,21 +9,30 @@ tags:
|
||||
---
|
||||
|
||||
## Intent
|
||||
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template method lets
|
||||
subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
|
||||
|
||||
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template
|
||||
Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's
|
||||
structure.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
|
||||
> The general steps in stealing an item are the same. First you pick the target, next you confuse him somehow and finally you steal the item. However there are many ways to implement these steps.
|
||||
> The general steps in stealing an item are the same. First you pick the target, next you confuse
|
||||
> him somehow and finally you steal the item. However there are many ways to implement these steps.
|
||||
|
||||
In plain words
|
||||
|
||||
> Template Method pattern outlines the general steps in the parent class and lets the concrete child implementations define the details.
|
||||
> Template Method pattern outlines the general steps in the parent class and lets the concrete child
|
||||
> implementations define the details.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> In object-oriented programming, the template method is one of the behavioral design patterns identified by Gamma et al. in the book Design Patterns. The template method is a method in a superclass, usually an abstract superclass, and defines the skeleton of an operation in terms of a number of high-level steps. These steps are themselves implemented by additional helper methods in the same class as the template method.
|
||||
> In object-oriented programming, the template method is one of the behavioral design patterns
|
||||
> identified by Gamma et al. in the book Design Patterns. The template method is a method in a
|
||||
> superclass, usually an abstract superclass, and defines the skeleton of an operation in terms of
|
||||
> a number of high-level steps. These steps are themselves implemented by additional helper methods
|
||||
> in the same class as the template method.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
@@ -120,9 +129,11 @@ And finally we show how the halfling thief utilizes the different stealing metho
|
||||
```
|
||||
|
||||
## Class diagram
|
||||

|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
The Template Method pattern should be used
|
||||
|
||||
* To implement the invariant parts of an algorithm once and leave it up to subclasses to implement the behavior that can vary
|
||||
|
Before Width: | Height: | Size: 18 KiB |
@@ -1,66 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
|
||||
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
|
||||
<class id="1" language="java" name="com.iluwatar.templatemethod.SubtleMethod" project="template-method"
|
||||
file="/template-method/src/main/java/com/iluwatar/templatemethod/SubtleMethod.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="142" width="174" x="-90" y="683"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="2" language="java" name="com.iluwatar.templatemethod.StealingMethod" project="template-method"
|
||||
file="/template-method/src/main/java/com/iluwatar/templatemethod/StealingMethod.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="159" width="177" x="17" y="484"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="3" language="java" name="com.iluwatar.templatemethod.HalflingThief" project="template-method"
|
||||
file="/template-method/src/main/java/com/iluwatar/templatemethod/HalflingThief.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="124" width="235" x="17" y="320"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="4" language="java" name="com.iluwatar.templatemethod.HitAndRunMethod" project="template-method"
|
||||
file="/template-method/src/main/java/com/iluwatar/templatemethod/HitAndRunMethod.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="142" width="174" x="124" y="683"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<association id="5">
|
||||
<end type="SOURCE" refId="3" navigable="false">
|
||||
<attribute id="6" name="method"/>
|
||||
<multiplicity id="7" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="2" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<generalization id="8">
|
||||
<end type="SOURCE" refId="4"/>
|
||||
<end type="TARGET" refId="2"/>
|
||||
</generalization>
|
||||
<generalization id="9">
|
||||
<end type="SOURCE" refId="1"/>
|
||||
<end type="TARGET" refId="2"/>
|
||||
</generalization>
|
||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</classifier-display>
|
||||
<association-display labels="true" multiplicity="true"/>
|
||||
</class-diagram>
|
Before Width: | Height: | Size: 34 KiB |
BIN
template-method/etc/template_method_urm.png
Normal file
After Width: | Height: | Size: 36 KiB |
@@ -9,16 +9,19 @@ tags:
|
||||
---
|
||||
|
||||
## Intent
|
||||
It is often the case that tasks to be executed are short-lived and
|
||||
the number of tasks is large. Creating a new thread for each task would make
|
||||
the system spend more time creating and destroying the threads than executing
|
||||
the actual tasks. Thread Pool solves this problem by reusing existing threads
|
||||
and eliminating the latency of creating new threads.
|
||||
|
||||
It is often the case that tasks to be executed are short-lived and the number of tasks is large.
|
||||
Creating a new thread for each task would make the system spend more time creating and destroying
|
||||
the threads than executing the actual tasks. Thread Pool solves this problem by reusing existing
|
||||
threads and eliminating the latency of creating new threads.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
|
||||
> We have a large number of relatively short tasks at hand. We need to peel huge amounts of potatoes and serve mighty amount of coffee cups. Creating a new thread for each task would be a waste so we establish a thread pool.
|
||||
> We have a large number of relatively short tasks at hand. We need to peel huge amounts of potatoes
|
||||
> and serve mighty amount of coffee cups. Creating a new thread for each task would be a waste so we
|
||||
> establish a thread pool.
|
||||
|
||||
In plain words
|
||||
|
||||
@@ -26,11 +29,18 @@ In plain words
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> In computer programming, a thread pool is a software design pattern for achieving concurrency of execution in a computer program. Often also called a replicated workers or worker-crew model, a thread pool maintains multiple threads waiting for tasks to be allocated for concurrent execution by the supervising program. By maintaining a pool of threads, the model increases performance and avoids latency in execution due to frequent creation and destruction of threads for short-lived tasks. The number of available threads is tuned to the computing resources available to the program, such as a parallel task queue after completion of execution.
|
||||
> In computer programming, a thread pool is a software design pattern for achieving concurrency of
|
||||
> execution in a computer program. Often also called a replicated workers or worker-crew model,
|
||||
> a thread pool maintains multiple threads waiting for tasks to be allocated for concurrent
|
||||
> execution by the supervising program. By maintaining a pool of threads, the model increases
|
||||
> performance and avoids latency in execution due to frequent creation and destruction of threads
|
||||
> for short-lived tasks. The number of available threads is tuned to the computing resources
|
||||
> available to the program, such as a parallel task queue after completion of execution.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
Let's first look at our task hierarchy. We have a base class and then concrete CoffeeMakingTask and PotatoPeelingTask.
|
||||
Let's first look at our task hierarchy. We have a base class and then concrete `CoffeeMakingTask`
|
||||
and `PotatoPeelingTask`.
|
||||
|
||||
```java
|
||||
public abstract class Task {
|
||||
@@ -88,8 +98,8 @@ public class PotatoPeelingTask extends Task {
|
||||
}
|
||||
```
|
||||
|
||||
Next we present a runnable Worker class that the thread pool will utilize to handle all the potato peeling and coffee
|
||||
making.
|
||||
Next we present a runnable `Worker` class that the thread pool will utilize to handle all the potato
|
||||
peeling and coffee making.
|
||||
|
||||
```java
|
||||
public class Worker implements Runnable {
|
||||
@@ -156,9 +166,11 @@ Now we are ready to show the full example in action.
|
||||
```
|
||||
|
||||
## Class diagram
|
||||

|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Thread Pool pattern when
|
||||
|
||||
* You have a large number of short-lived tasks to be executed in parallel
|
||||
|
Before Width: | Height: | Size: 14 KiB |
@@ -1,62 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
|
||||
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
|
||||
<class id="1" language="java" name="com.iluwatar.Task" project="thread-pool"
|
||||
file="/thread-pool/src/main/java/com/iluwatar/Task.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="343" y="579"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="2" language="java" name="com.iluwatar.Worker" project="thread-pool"
|
||||
file="/thread-pool/src/main/java/com/iluwatar/Worker.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="344" y="389"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="3" language="java" name="com.iluwatar.CoffeeMakingTask" project="thread-pool"
|
||||
file="/thread-pool/src/main/java/com/iluwatar/CoffeeMakingTask.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="124" width="156" x="194" y="717"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="4" language="java" name="com.iluwatar.PotatoPeelingTask" project="thread-pool"
|
||||
file="/thread-pool/src/main/java/com/iluwatar/PotatoPeelingTask.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="124" width="169" x="390" y="717"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<association id="5">
|
||||
<end type="SOURCE" refId="2" navigable="false">
|
||||
<attribute id="6" name="task"/>
|
||||
<multiplicity id="7" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="1" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<generalization id="8">
|
||||
<end type="SOURCE" refId="4"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</generalization>
|
||||
<generalization id="9">
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</generalization>
|
||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</classifier-display>
|
||||
<association-display labels="true" multiplicity="true"/>
|
||||
</class-diagram>
|
BIN
thread-pool/etc/thread_pool_urm.png
Normal file
After Width: | Height: | Size: 29 KiB |
@@ -10,12 +10,15 @@ tags:
|
||||
---
|
||||
|
||||
## Intent
|
||||
|
||||
Ensure that a given client is not able to access service resources more than the assigned limit.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
|
||||
> A large multinational corporation offers API to its customers. The API is rate-limited and each customer can only make certain amount of calls per second.
|
||||
> A large multinational corporation offers API to its customers. The API is rate-limited and each
|
||||
> customer can only make certain amount of calls per second.
|
||||
|
||||
In plain words
|
||||
|
||||
@@ -23,7 +26,9 @@ In plain words
|
||||
|
||||
[Microsoft documentation](https://docs.microsoft.com/en-us/azure/architecture/patterns/throttling) says
|
||||
|
||||
> Control the consumption of resources used by an instance of an application, an individual tenant, or an entire service. This can allow the system to continue to function and meet service level agreements, even when an increase in demand places an extreme load on resources.
|
||||
> Control the consumption of resources used by an instance of an application, an individual tenant,
|
||||
> or an entire service. This can allow the system to continue to function and meet service level
|
||||
> agreements, even when an increase in demand places an extreme load on resources.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
@@ -77,7 +82,8 @@ public final class CallsCount {
|
||||
}
|
||||
```
|
||||
|
||||
Next we introduce the service that the tenants are calling. To track the call count we use the throttler timer.
|
||||
Next we introduce the service that the tenants are calling. To track the call count we use the
|
||||
throttler timer.
|
||||
|
||||
```java
|
||||
public interface Throttler {
|
||||
@@ -134,7 +140,8 @@ class B2BService {
|
||||
}
|
||||
```
|
||||
|
||||
Now we are ready to see the full example in action. Tenant Adidas is rate-limited to 5 calls per second and Nike to 6.
|
||||
Now we are ready to see the full example in action. Tenant Adidas is rate-limited to 5 calls per
|
||||
second and Nike to 6.
|
||||
|
||||
```java
|
||||
public static void main(String[] args) {
|
||||
@@ -171,9 +178,11 @@ Now we are ready to see the full example in action. Tenant Adidas is rate-limite
|
||||
|
||||
|
||||
## Class diagram
|
||||

|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
The Throttling pattern should be used:
|
||||
|
||||
* When a service access needs to be restricted to not have high impacts on the performance of the service.
|
||||
|
Before Width: | Height: | Size: 49 KiB |
@@ -1,88 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.2.2" icons="true" always-add-relationships="false" generalizations="true" realizations="true"
|
||||
associations="true" dependencies="false" nesting-relationships="true" router="FAN">
|
||||
<class id="1" language="java" name="com.iluwatar.throttling.CallsCount" project="throttling"
|
||||
file="/throttling/src/main/java/com/iluwatar/throttling/CallsCount.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="211" width="256" x="656" y="228"/>
|
||||
<display autosize="false" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="2" language="java" name="com.iluwatar.throttling.Tenant" project="throttling"
|
||||
file="/throttling/src/main/java/com/iluwatar/throttling/Tenant.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="465" y="524"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="3" language="java" name="com.iluwatar.throttling.B2BService" project="throttling"
|
||||
file="/throttling/src/main/java/com/iluwatar/throttling/B2BService.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="464" y="192"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<interface id="4" language="java" name="com.iluwatar.throttling.timer.Throttler" project="throttling"
|
||||
file="/throttling/src/main/java/com/iluwatar/throttling/timer/Throttler.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="167" y="174"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<class id="5" language="java" name="com.iluwatar.throttling.timer.ThrottleTimerImpl" project="throttling"
|
||||
file="/throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="166" y="396"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<association id="6">
|
||||
<end type="SOURCE" refId="3" navigable="false">
|
||||
<attribute id="7" name="callsCount"/>
|
||||
<multiplicity id="8" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="1" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<dependency id="9">
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</dependency>
|
||||
<dependency id="10">
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="2"/>
|
||||
</dependency>
|
||||
<association id="11">
|
||||
<end type="SOURCE" refId="5" navigable="false">
|
||||
<attribute id="12" name="callsCount"/>
|
||||
<multiplicity id="13" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="1" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<dependency id="14">
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</dependency>
|
||||
<realization id="15">
|
||||
<end type="SOURCE" refId="5"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</realization>
|
||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</classifier-display>
|
||||
<association-display labels="true" multiplicity="true"/>
|
||||
</class-diagram>
|
BIN
throttling/etc/throttling_urm.png
Normal file
After Width: | Height: | Size: 52 KiB |
@@ -24,7 +24,6 @@
|
||||
package com.iluwatar.throttling;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import org.slf4j.Logger;
|
||||
|
@@ -9,14 +9,18 @@ tags:
|
||||
---
|
||||
|
||||
## Intent
|
||||
Tolerant Reader is an integration pattern that helps creating robust communication systems. The idea is to be as
|
||||
tolerant as possible when reading data from another service. This way, when the communication schema changes, the
|
||||
readers must not break.
|
||||
|
||||
Tolerant Reader is an integration pattern that helps creating robust communication systems. The idea
|
||||
is to be as tolerant as possible when reading data from another service. This way, when the
|
||||
communication schema changes, the readers must not break.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
|
||||
> We are persisting rainbowfish objects to file and later on they need to be restored. What makes it problematic is that rainbowfish data structure is versioned and evolves over time. New version of rainbowfish needs to be able to restore old versions as well.
|
||||
> We are persisting rainbowfish objects to file and later on they need to be restored. What makes it
|
||||
> problematic is that rainbowfish data structure is versioned and evolves over time. New version of
|
||||
> rainbowfish needs to be able to restore old versions as well.
|
||||
|
||||
In plain words
|
||||
|
||||
@@ -24,11 +28,11 @@ In plain words
|
||||
|
||||
[Robustness Principle](https://java-design-patterns.com/principles/#robustness-principle) says
|
||||
|
||||
> Be conservative in what you do, be liberal in what you accept from others
|
||||
> Be conservative in what you do, be liberal in what you accept from others.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
Here's the versioned rainbowfish. Notice how the second version introduces additional properties.
|
||||
Here's the versioned `RainbowFish`. Notice how the second version introduces additional properties.
|
||||
|
||||
```java
|
||||
public class RainbowFish implements Serializable {
|
||||
@@ -104,7 +108,8 @@ public class RainbowFishV2 extends RainbowFish {
|
||||
}
|
||||
```
|
||||
|
||||
Next we introduce the rainbowfish serializer. This is the class that implements the Tolerant Reader pattern.
|
||||
Next we introduce the `RainbowFishSerializer`. This is the class that implements the Tolerant Reader
|
||||
pattern.
|
||||
|
||||
```java
|
||||
public final class RainbowFishSerializer {
|
||||
@@ -185,18 +190,23 @@ And finally here's the full example in action.
|
||||
LOGGER.info("deserializedFishV2 name={} age={} length={} weight={}",
|
||||
deserializedFishV2.getName(), deserializedFishV2.getAge(),
|
||||
deserializedFishV2.getLengthMeters(), deserializedFishV2.getWeightTons());
|
||||
|
||||
// fishV1 name=Zed age=10 length=11 weight=12
|
||||
// deserializedFishV1 name=Zed age=10 length=11 weight=12
|
||||
// fishV2 name=Scar age=5 length=12 weight=15 sleeping=true hungry=true angry=true
|
||||
// deserializedFishV2 name=Scar age=5 length=12 weight=15
|
||||
```
|
||||
|
||||
Program output:
|
||||
|
||||
```
|
||||
fishV1 name=Zed age=10 length=11 weight=12
|
||||
deserializedFishV1 name=Zed age=10 length=11 weight=12
|
||||
fishV2 name=Scar age=5 length=12 weight=15 sleeping=true hungry=true angry=true
|
||||
deserializedFishV2 name=Scar age=5 length=12 weight=15
|
||||
```
|
||||
|
||||
## Class diagram
|
||||

|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Tolerant Reader pattern when
|
||||
|
||||
* The communication schema can evolve and change and yet the receiving side should not break
|
||||
|
Before Width: | Height: | Size: 20 KiB |
@@ -1,52 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
|
||||
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
|
||||
<class id="1" language="java" name="com.iluwatar.tolerantreader.RainbowFishSerializer" project="tolerant-reader"
|
||||
file="/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishSerializer.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="123" y="415"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="2" language="java" name="com.iluwatar.tolerantreader.RainbowFishV2" project="tolerant-reader"
|
||||
file="/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishV2.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="389" y="685"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="3" language="java" name="com.iluwatar.tolerantreader.RainbowFish" project="tolerant-reader"
|
||||
file="/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFish.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="389" y="404"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<dependency id="4">
|
||||
<end type="SOURCE" refId="1"/>
|
||||
<end type="TARGET" refId="3"/>
|
||||
</dependency>
|
||||
<dependency id="5">
|
||||
<end type="SOURCE" refId="1"/>
|
||||
<end type="TARGET" refId="2"/>
|
||||
</dependency>
|
||||
<generalization id="6">
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="3"/>
|
||||
</generalization>
|
||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</classifier-display>
|
||||
<association-display labels="true" multiplicity="true"/>
|
||||
</class-diagram>
|
BIN
tolerant-reader/etc/tolerant_reader_urm.png
Normal file
After Width: | Height: | Size: 45 KiB |
@@ -10,22 +10,23 @@ tags:
|
||||
|
||||
## Intent
|
||||
|
||||
Trampoline pattern is used for implementing algorithms recursively in Java without blowing the stack and to interleave
|
||||
the execution of functions without hard coding them together.
|
||||
Trampoline pattern is used for implementing algorithms recursively in Java without blowing the stack
|
||||
and to interleave the execution of functions without hard coding them together.
|
||||
|
||||
## Explanation
|
||||
|
||||
Recursion is a frequently adopted technique for solving algorithmic problems in a divide and conquer
|
||||
style. For example calculating fibonacci accumulating sum and factorials. In these kinds of problems recursion is
|
||||
more straightforward than their loop counterpart. Furthermore recursion may need less code and looks more concise.
|
||||
There is a saying that every recursion problem can be solved using a loop with the cost of writing code that is more
|
||||
difficult to understand.
|
||||
style. For example calculating fibonacci accumulating sum and factorials. In these kinds of problems
|
||||
recursion is more straightforward than their loop counterpart. Furthermore recursion may need less
|
||||
code and looks more concise. There is a saying that every recursion problem can be solved using
|
||||
a loop with the cost of writing code that is more difficult to understand.
|
||||
|
||||
However recursion type solutions have one big caveat. For each recursive call it typically needs an intermediate value
|
||||
stored and there is a limited amount of stack memory available. Running out of stack memory creates a stack overflow
|
||||
error and halts the program execution.
|
||||
However recursion type solutions have one big caveat. For each recursive call it typically needs
|
||||
an intermediate value stored and there is a limited amount of stack memory available. Running out of
|
||||
stack memory creates a stack overflow error and halts the program execution.
|
||||
|
||||
Trampoline pattern is a trick that allows us define recursive algorithms in Java without blowing the stack.
|
||||
Trampoline pattern is a trick that allows us define recursive algorithms in Java without blowing the
|
||||
stack.
|
||||
|
||||
Real world example
|
||||
|
||||
@@ -37,14 +38,18 @@ In plain words
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> In Java, trampoline refers to using reflection to avoid using inner classes, for example in event listeners. The time overhead of a reflection call is traded for the space overhead of an inner class. Trampolines in Java usually involve the creation of a GenericListener to pass events to an outer class.
|
||||
> In Java, trampoline refers to using reflection to avoid using inner classes, for example in event
|
||||
> listeners. The time overhead of a reflection call is traded for the space overhead of an inner
|
||||
> class. Trampolines in Java usually involve the creation of a GenericListener to pass events to
|
||||
> an outer class.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
Here's the `Trampoline` implementation in Java.
|
||||
|
||||
When `get` is called on the returned Trampoline, internally it will iterate calling `jump` on the returned `Trampoline`
|
||||
as long as the concrete instance returned is `Trampoline`, stopping once the returned instance is `done`.
|
||||
When `get` is called on the returned Trampoline, internally it will iterate calling `jump` on the
|
||||
returned `Trampoline` as long as the concrete instance returned is `Trampoline`, stopping once the
|
||||
returned instance is `done`.
|
||||
|
||||
```java
|
||||
public interface Trampoline<T> {
|
||||
@@ -110,15 +115,21 @@ Using the `Trampoline` to get Fibonacci values.
|
||||
log.info("start pattern");
|
||||
var result = loop(10, 1).result();
|
||||
log.info("result {}", result);
|
||||
|
||||
// start pattern
|
||||
// result 3628800
|
||||
```
|
||||
|
||||
Program output:
|
||||
|
||||
```
|
||||
start pattern
|
||||
result 3628800
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Trampoline pattern when
|
||||
|
||||
* For implementing tail recursive function. This pattern allows to switch on a stackless operation.
|
||||
|