Compare commits

...

95 Commits

Author SHA1 Message Date
6f592f5e8a docs: update .all-contributorsrc [skip ci] 2020-09-13 14:23:53 +00:00
74b968942f docs: update README.md [skip ci] 2020-09-13 14:23:52 +00:00
ebc0e8b3cd Merge pull request #1522 from swarajsaaj/master
#1313 Add Separated Interface pattern
2020-09-13 17:21:28 +03:00
9088ac51f6 #1313 Rename DomesticTax,ForeignTax and review fixes 2020-09-12 22:35:40 +05:30
c8f7a8f0e6 Merge pull request #1523 from iluwatar/all-contributors/add-vdlald
docs: add vdlald as a contributor
2020-09-12 20:02:32 +03:00
c63af2ccbf docs: update .all-contributorsrc [skip ci] 2020-09-12 17:00:59 +00:00
9f3f5322d2 docs: update README.md [skip ci] 2020-09-12 17:00:58 +00:00
5607a4974c Merge pull request #1517 from vdlald/847
847
2020-09-12 19:57:29 +03:00
a2967c5a40 #1313 Add documentation and license header 2020-09-10 03:22:00 +05:30
7fd7735527 #1313 Add separated-interface module to parent pom 2020-09-10 03:10:58 +05:30
f6942cf18d #1313 Add Separated Interface design pattern 2020-09-10 02:57:56 +05:30
ef326ee77e Update README.md 2020-09-06 19:56:07 +03:00
8b5f532a50 Update README.md 2020-09-06 19:55:38 +03:00
a1da1e4973 Cleanup factory 2020-09-06 19:46:13 +03:00
9d21dff855 Merge pull request #1520 from iluwatar/all-contributors/add-ravening
docs: add ravening as a contributor
2020-09-06 19:39:08 +03:00
9d75592e8b Merge branch 'master' into all-contributors/add-ravening 2020-09-06 19:38:44 +03:00
8d6738b729 docs: update .all-contributorsrc [skip ci] 2020-09-06 16:37:04 +00:00
3205dc2cf0 docs: update README.md [skip ci] 2020-09-06 16:37:03 +00:00
16e1863ae7 Merge pull request #1519 from iluwatar/all-contributors/add-samilAyoub
docs: add samilAyoub as a contributor
2020-09-06 19:36:35 +03:00
b9db3c4763 docs: update .all-contributorsrc [skip ci] 2020-09-06 16:35:58 +00:00
d72206ba72 docs: update README.md [skip ci] 2020-09-06 16:35:57 +00:00
922c699e49 Merge pull request #1516 from samilAyoub/add-simple-factory
Add Simple Factory Pattern implementation
2020-09-06 19:33:03 +03:00
bab48efd7c fix style 2020-09-06 12:01:48 +03:00
29eecfd048 forgot to run the App 2020-09-06 11:52:16 +03:00
87cf6b791c refactor 2020-09-06 11:48:40 +03:00
2e36a11e24 remove lombok, related to #1503 2020-09-06 11:42:39 +03:00
bf41b1d9c9 Updates README.md:
- Adding class diagram
- Adding Pros and Cons
- replace "" with ''
2020-09-05 18:39:28 +01:00
b3ef214cd6 Change tabs to spaces in pom.xml 2020-09-04 22:02:19 +01:00
6caf78e4e5 updates :
- Using lambda expression to create cars
- Using spaces instead of tabs in pom.xml
2020-09-04 21:21:51 +01:00
bd48d6ce10 refactor 2020-09-04 17:31:50 +03:00
8b26452c75 bug fixing 2020-09-03 22:58:15 +01:00
2bb252e08f Clean the code 2020-09-03 22:41:55 +01:00
a023cfbb1a Merge branch 'master' into add-simple-factory 2020-09-03 22:26:49 +01:00
badf0c6b8c - README.md is added
- Change the name to factory is done
- Local variable type inference is used
2020-09-03 22:08:54 +01:00
c9718a5227 add README file 2020-09-03 21:08:28 +01:00
e89042a782 remove boilerplate code 2020-09-03 20:04:47 +03:00
fb890e80dd refactor 2020-09-03 20:02:52 +03:00
b423fd30d4 Fix bugs, clean the code and add unit tests. 2020-09-02 18:12:42 +01:00
3df8472bf8 Merge pull request #1515 from fedorskvorcov/fix-typo
Remove unnecessary word from text
2020-09-02 19:59:07 +03:00
ac98b31b68 Add Maven Assembly plugin to pom.xml 2020-09-02 14:09:44 +01:00
46b23f322f Add Simple Factory Pattern implementation
Java source code demonstrate simple factory design pattern
2020-09-02 13:46:53 +01:00
e231cd8d1a Remove unnecessary word from text 2020-09-02 12:32:02 +03:00
19378f3fdd Update README.md 2020-09-01 20:25:39 +03:00
3f4d637510 Update README.md 2020-09-01 20:18:10 +03:00
25cca3547d Update README.md 2020-09-01 20:06:47 +03:00
b9b6777d15 Update README.md 2020-09-01 19:55:22 +03:00
2a5b8c977a Merge pull request #1514 from iluwatar/all-contributors/add-fedorskvorcov
docs: add fedorskvorcov as a contributor
2020-09-01 16:40:23 +03:00
daa94c7b6d docs: update .all-contributorsrc [skip ci] 2020-09-01 13:39:33 +00:00
7aca64a3c9 docs: update README.md [skip ci] 2020-09-01 13:39:32 +00:00
6628bccecc Merge pull request #1513 from fedorskvorcov/fix-typo
Fix typo in comment
2020-09-01 16:38:44 +03:00
aebdb88a83 Fix typo in comment 2020-09-01 09:51:46 +03:00
9c0c17b87a Merge pull request #1512 from xiaod-dev/translation-zh
Translation zh
2020-08-31 20:17:39 +03:00
20fac32ac2 finish Chinese translation of observer and strategy 2020-08-31 17:18:59 +08:00
82842d614b Update README.md 2020-08-30 20:08:34 +03:00
9b71479d04 Update README.md 2020-08-30 19:34:10 +03:00
3c4ae6c4ca Update README.md 2020-08-30 19:17:45 +03:00
9ff42389c6 Merge pull request #1511 from ohbus/master
Configure build to disable shallow clone
2020-08-30 11:52:13 +03:00
b80b9354c6 Update maven-ci.yml 2020-08-30 02:31:06 +05:30
67d1d16e1f Update README.md 2020-08-29 22:13:55 +03:00
bc35911475 Update README.md 2020-08-29 22:02:10 +03:00
b5c6a89ec9 Update README.md 2020-08-29 21:55:51 +03:00
74360a7ecb Update README.md 2020-08-29 21:51:32 +03:00
3544a8366f Update README.md 2020-08-29 21:38:58 +03:00
bcca9beb4d Update README.md 2020-08-29 21:29:15 +03:00
6606d6cd08 Update README.md 2020-08-29 21:21:01 +03:00
f3fd49870c Update README.md 2020-08-29 21:05:30 +03:00
1fbef60f37 Update README.md 2020-08-29 21:00:17 +03:00
b77a05f0fb Update README.md 2020-08-29 20:46:40 +03:00
0ee03db4d0 Update README.md 2020-08-29 20:38:04 +03:00
c541176b38 Update README.md 2020-08-29 20:26:37 +03:00
b53856b64f Merge pull request #1509 from ohbus/master
Cleaning up unnecessary code from the CI yaml and CI server version upgrade
2020-08-29 20:19:42 +03:00
1973d1bc63 Update maven-pr-builder.yml
upgraded build server runtime from Ubuntu 18.04 to 20.04 LTS for the PR builder as well
2020-08-29 19:35:20 +05:30
f5886325ec Update maven-ci.yml
upgraded build server runtime from Ubuntu 18.04 to 20.04 LTS
2020-08-29 19:34:43 +05:30
8afe4c314a Update README.md 2020-08-29 16:56:52 +03:00
2dd2cfb8ca Update README.md 2020-08-29 16:49:45 +03:00
8512c65aef Update README.md 2020-08-29 16:42:46 +03:00
6373f7b115 Update README.md 2020-08-29 16:38:20 +03:00
e8b42bd135 Update README.md 2020-08-29 16:23:28 +03:00
2bb2134636 Update README.md 2020-08-29 16:17:15 +03:00
675b2f14b2 Update README.md 2020-08-29 16:10:59 +03:00
338c146c78 Update maven-pr-builder.yml 2020-08-29 17:39:50 +05:30
8135dbecdb Update maven-ci.yml 2020-08-29 17:36:31 +05:30
a4f2d14848 Update README.md 2020-08-29 12:01:23 +03:00
96c16a8f3a Update README.md 2020-08-29 11:29:30 +03:00
47e746c3ba Update maven-pr-builder.yml
removed the if checking block for building Pull Requests as this was redundant code.
2020-08-28 12:26:27 +05:30
7118ccafa9 Update maven-ci.yml
Removed if clause for building code in main codebase from the CI pipeline.
2020-08-28 12:17:38 +05:30
8983f9c11c Update README.md 2020-08-26 21:55:05 +03:00
9b464e0be1 Merge pull request #1507 from amit1307/upgrade-mockito-1486
Upgrade Mockito version
2020-08-26 21:20:11 +03:00
b07d33f332 Upgrade Mockito version to latest 2020-08-26 00:09:30 +01:00
6c4c6097be Merge branch 'master' of https://github.com/iluwatar/java-design-patterns 2020-08-25 23:21:25 +01:00
9dd46d7b4a Update README.md 2020-08-25 21:42:42 +03:00
723afb85ba Set version for next development iteration 2020-08-25 21:21:36 +03:00
a0e5d061cb Milestone 1.23.0 2020-08-25 21:20:30 +03:00
1e385056fc finish translate adapter pattern into chinese 2020-08-19 17:10:14 +08:00
9b25d302b7 Fix broken logging in service layer 2020-07-26 21:57:15 +01:00
233 changed files with 3008 additions and 1281 deletions

View File

@ -1082,7 +1082,8 @@
"avatar_url": "https://avatars1.githubusercontent.com/u/10645273?v=4",
"profile": "https://github.com/ravening",
"contributions": [
"code"
"code",
"review"
]
},
{
@ -1176,6 +1177,42 @@
"contributions": [
"code"
]
},
{
"login": "fedorskvorcov",
"name": "Fedor Skvorcov",
"avatar_url": "https://avatars3.githubusercontent.com/u/43882212?v=4",
"profile": "https://github.com/fedorskvorcov",
"contributions": [
"code"
]
},
{
"login": "samilAyoub",
"name": "samilAyoub",
"avatar_url": "https://avatars0.githubusercontent.com/u/61546990?v=4",
"profile": "https://github.com/samilAyoub",
"contributions": [
"code"
]
},
{
"login": "vdlald",
"name": "Vladislav Golubinov",
"avatar_url": "https://avatars0.githubusercontent.com/u/29997701?v=4",
"profile": "https://github.com/vdlald",
"contributions": [
"code"
]
},
{
"login": "swarajsaaj",
"name": "Swaraj",
"avatar_url": "https://avatars2.githubusercontent.com/u/6285049?v=4",
"profile": "https://github.com/swarajsaaj",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 4,

View File

@ -33,10 +33,13 @@ on:
jobs:
build:
runs-on: ubuntu-18.04
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
with:
# Disabling shallow clone for improving relevancy of SonarQube reporting
fetch-depth: 0
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
@ -49,14 +52,11 @@ jobs:
${{ runner.os }}-maven-
# Some tests need screen access
- name: Install xvfb
run: sudo apt-get install xvfb
# SonarQube scan does not work for forked repositories
run: sudo apt-get install -y xvfb
# The SonarQube analysis is only for the master branch of the main repository.
# SonarQube scan does not work for forked repositories try changing it to xvfb-run mvn clean verify
# See https://jira.sonarsource.com/browse/MMF-1371
- name: Build with Maven
if: github.ref != 'refs/heads/master'
run: xvfb-run mvn clean verify
- name: Build with Maven and run SonarQube analysis
if: github.ref == 'refs/heads/master'
run: xvfb-run mvn clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
env:
# These two env variables are needed for sonar analysis

View File

@ -33,7 +33,7 @@ on:
jobs:
build:
runs-on: ubuntu-18.04
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
@ -49,9 +49,9 @@ jobs:
${{ runner.os }}-maven-
# Some tests need screen access
- name: Install xvfb
run: sudo apt-get install xvfb
# SonarQube scan does not work for forked repositories
run: sudo apt-get install -y xvfb
# This worflow is only for building Pull Requests, the master branch runs Sonar analysis on the main repository.
# SonarQube scan does not work for forked repositories.
# See https://jira.sonarsource.com/browse/MMF-1371
- name: Build with Maven
if: github.ref != 'refs/heads/master'
run: xvfb-run mvn clean verify

View File

@ -10,7 +10,7 @@
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](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 -->
[![All Contributors](https://img.shields.io/badge/all_contributors-129-orange.svg?style=flat-square)](#contributors-)
[![All Contributors](https://img.shields.io/badge/all_contributors-133-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
# Introduction
@ -246,7 +246,7 @@ This project is licensed under the terms of the MIT license.
<tr>
<td align="center"><a href="https://github.com/nishant"><img src="https://avatars2.githubusercontent.com/u/15331971?v=4" width="100px;" alt=""/><br /><sub><b>Nishant Arora</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=nishant" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/raja-peeyush-kumar-singh"><img src="https://avatars0.githubusercontent.com/u/5496024?v=4" width="100px;" alt=""/><br /><sub><b>Peeyush</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=raja-peeyush-kumar-singh" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/ravening"><img src="https://avatars1.githubusercontent.com/u/10645273?v=4" width="100px;" alt=""/><br /><sub><b>Rakesh</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ravening" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/ravening"><img src="https://avatars1.githubusercontent.com/u/10645273?v=4" width="100px;" alt=""/><br /><sub><b>Rakesh</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ravening" title="Code">💻</a> <a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Aravening" title="Reviewed Pull Requests">👀</a></td>
<td align="center"><a href="https://github.com/vINCENT8888801"><img src="https://avatars0.githubusercontent.com/u/8037883?v=4" width="100px;" alt=""/><br /><sub><b>Wei Seng</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=vINCENT8888801" title="Code">💻</a></td>
</tr>
<tr>
@ -263,6 +263,12 @@ This project is licensed under the terms of the MIT license.
</tr>
<tr>
<td align="center"><a href="https://www.stefan-birkner.de"><img src="https://avatars1.githubusercontent.com/u/711349?v=4" width="100px;" alt=""/><br /><sub><b>Stefan Birkner</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=stefanbirkner" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/fedorskvorcov"><img src="https://avatars3.githubusercontent.com/u/43882212?v=4" width="100px;" alt=""/><br /><sub><b>Fedor Skvorcov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=fedorskvorcov" title="Code">💻</a></td>
<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>
</tr>
</table>

View File

@ -21,7 +21,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>abstract-document</artifactId>
<dependencies>

View File

@ -22,7 +22,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>abstract-factory</artifactId>
<dependencies>

View File

@ -23,7 +23,6 @@
package com.iluwatar.abstractfactory;
import com.iluwatar.abstractfactory.App.FactoryMaker.KingdomType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -41,84 +40,14 @@ import org.slf4j.LoggerFactory;
* and its implementations ( {@link ElfKingdomFactory}, {@link OrcKingdomFactory}). The example uses
* both concrete implementations to create a king, a castle and an army.
*/
public class App {
public class App implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
private static Logger log = LoggerFactory.getLogger(App.class);
private King king;
private Castle castle;
private Army army;
private final Kingdom kingdom = new Kingdom();
/**
* Creates kingdom.
*/
public void createKingdom(final KingdomFactory factory) {
setKing(factory.createKing());
setCastle(factory.createCastle());
setArmy(factory.createArmy());
}
King getKing(final KingdomFactory factory) {
return factory.createKing();
}
public King getKing() {
return king;
}
private void setKing(final King king) {
this.king = king;
}
Castle getCastle(final KingdomFactory factory) {
return factory.createCastle();
}
public Castle getCastle() {
return castle;
}
private void setCastle(final Castle castle) {
this.castle = castle;
}
Army getArmy(final KingdomFactory factory) {
return factory.createArmy();
}
public Army getArmy() {
return army;
}
private void setArmy(final Army army) {
this.army = army;
}
/**
* The factory of kingdom factories.
*/
public static class FactoryMaker {
/**
* Enumeration for the different types of Kingdoms.
*/
public enum KingdomType {
ELF, ORC
}
/**
* The factory method to create KingdomFactory concrete objects.
*/
public static KingdomFactory makeFactory(KingdomType type) {
switch (type) {
case ELF:
return new ElfKingdomFactory();
case ORC:
return new OrcKingdomFactory();
default:
throw new IllegalArgumentException("KingdomType not supported.");
}
}
public Kingdom getKingdom() {
return kingdom;
}
/**
@ -127,19 +56,33 @@ public class App {
* @param args command line args
*/
public static void main(String[] args) {
var app = new App();
app.run();
}
LOGGER.info("Elf Kingdom");
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
LOGGER.info(app.getArmy().getDescription());
LOGGER.info(app.getCastle().getDescription());
LOGGER.info(app.getKing().getDescription());
@Override
public void run() {
log.info("Elf Kingdom");
createKingdom(Kingdom.FactoryMaker.KingdomType.ELF);
log.info(kingdom.getArmy().getDescription());
log.info(kingdom.getCastle().getDescription());
log.info(kingdom.getKing().getDescription());
LOGGER.info("Orc Kingdom");
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
LOGGER.info(app.getArmy().getDescription());
LOGGER.info(app.getCastle().getDescription());
LOGGER.info(app.getKing().getDescription());
log.info("Orc Kingdom");
createKingdom(Kingdom.FactoryMaker.KingdomType.ORC);
log.info(kingdom.getArmy().getDescription());
log.info(kingdom.getCastle().getDescription());
log.info(kingdom.getKing().getDescription());
}
/**
* Creates kingdom.
* @param kingdomType type of Kingdom
*/
public void createKingdom(final Kingdom.FactoryMaker.KingdomType kingdomType) {
final KingdomFactory kingdomFactory = Kingdom.FactoryMaker.makeFactory(kingdomType);
kingdom.setKing(kingdomFactory.createKing());
kingdom.setCastle(kingdomFactory.createCastle());
kingdom.setArmy(kingdomFactory.createArmy());
}
}

View File

@ -0,0 +1,59 @@
package com.iluwatar.abstractfactory;
public class Kingdom {
private King king;
private Castle castle;
private Army army;
public King getKing() {
return king;
}
public Castle getCastle() {
return castle;
}
public Army getArmy() {
return army;
}
public void setKing(King king) {
this.king = king;
}
public void setCastle(Castle castle) {
this.castle = castle;
}
public void setArmy(Army army) {
this.army = army;
}
/**
* The factory of kingdom factories.
*/
public static class FactoryMaker {
/**
* Enumeration for the different types of Kingdoms.
*/
public enum KingdomType {
ELF, ORC
}
/**
* The factory method to create KingdomFactory concrete objects.
*/
public static KingdomFactory makeFactory(KingdomType type) {
switch (type) {
case ELF:
return new ElfKingdomFactory();
case ORC:
return new OrcKingdomFactory();
default:
throw new IllegalArgumentException("KingdomType not supported.");
}
}
}
}

View File

@ -23,65 +23,71 @@
package com.iluwatar.abstractfactory;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.iluwatar.abstractfactory.App.FactoryMaker;
import com.iluwatar.abstractfactory.App.FactoryMaker.KingdomType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/**
* Test for abstract factory.
*/
public class AbstractFactoryTest {
private final App app = new App();
private KingdomFactory elfFactory;
private KingdomFactory orcFactory;
@BeforeEach
public void setUp() {
elfFactory = FactoryMaker.makeFactory(KingdomType.ELF);
orcFactory = FactoryMaker.makeFactory(KingdomType.ORC);
}
@Test
public void king() {
final var elfKing = app.getKing(elfFactory);
app.createKingdom(Kingdom.FactoryMaker.KingdomType.ELF);
final var kingdom = app.getKingdom();
final var elfKing = kingdom.getKing();
assertTrue(elfKing instanceof ElfKing);
assertEquals(ElfKing.DESCRIPTION, elfKing.getDescription());
final var orcKing = app.getKing(orcFactory);
app.createKingdom(Kingdom.FactoryMaker.KingdomType.ORC);
final var orcKing = kingdom.getKing();
assertTrue(orcKing instanceof OrcKing);
assertEquals(OrcKing.DESCRIPTION, orcKing.getDescription());
}
@Test
public void castle() {
final var elfCastle = app.getCastle(elfFactory);
app.createKingdom(Kingdom.FactoryMaker.KingdomType.ELF);
final var kingdom = app.getKingdom();
final var elfCastle = kingdom.getCastle();
assertTrue(elfCastle instanceof ElfCastle);
assertEquals(ElfCastle.DESCRIPTION, elfCastle.getDescription());
final var orcCastle = app.getCastle(orcFactory);
app.createKingdom(Kingdom.FactoryMaker.KingdomType.ORC);
final var orcCastle = kingdom.getCastle();
assertTrue(orcCastle instanceof OrcCastle);
assertEquals(OrcCastle.DESCRIPTION, orcCastle.getDescription());
}
@Test
public void army() {
final var elfArmy = app.getArmy(elfFactory);
app.createKingdom(Kingdom.FactoryMaker.KingdomType.ELF);
final var kingdom = app.getKingdom();
final var elfArmy = kingdom.getArmy();
assertTrue(elfArmy instanceof ElfArmy);
assertEquals(ElfArmy.DESCRIPTION, elfArmy.getDescription());
final var orcArmy = app.getArmy(orcFactory);
app.createKingdom(Kingdom.FactoryMaker.KingdomType.ORC);
final var orcArmy = kingdom.getArmy();
assertTrue(orcArmy instanceof OrcArmy);
assertEquals(OrcArmy.DESCRIPTION, orcArmy.getDescription());
}
@Test
public void createElfKingdom() {
app.createKingdom(elfFactory);
final var king = app.getKing();
final var castle = app.getCastle();
final var army = app.getArmy();
app.createKingdom(Kingdom.FactoryMaker.KingdomType.ELF);
final var kingdom = app.getKingdom();
final var king = kingdom.getKing();
final var castle = kingdom.getCastle();
final var army = kingdom.getArmy();
assertTrue(king instanceof ElfKing);
assertEquals(ElfKing.DESCRIPTION, king.getDescription());
assertTrue(castle instanceof ElfCastle);
@ -92,10 +98,12 @@ public class AbstractFactoryTest {
@Test
public void createOrcKingdom() {
app.createKingdom(orcFactory);
final var king = app.getKing();
final var castle = app.getCastle();
final var army = app.getArmy();
app.createKingdom(Kingdom.FactoryMaker.KingdomType.ORC);
final var kingdom = app.getKingdom();
final var king = kingdom.getKing();
final var castle = kingdom.getCastle();
final var army = kingdom.getArmy();
assertTrue(king instanceof OrcKing);
assertEquals(OrcKing.DESCRIPTION, king.getDescription());
assertTrue(castle instanceof OrcCastle);

View File

@ -21,7 +21,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>acyclic-visitor</artifactId>

View File

@ -22,7 +22,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>adapter</artifactId>
<dependencies>

View File

@ -20,7 +20,7 @@
<parent>
<artifactId>aggregator-microservices</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>aggregator-service</artifactId>

View File

@ -20,7 +20,7 @@
<parent>
<artifactId>aggregator-microservices</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -20,7 +20,7 @@
<parent>
<artifactId>aggregator-microservices</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>inventory-microservice</artifactId>

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>aggregator-microservices</artifactId>

View File

@ -20,7 +20,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ambassador</artifactId>

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>api-gateway</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>api-gateway-service</artifactId>

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>api-gateway</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>image-microservice</artifactId>

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>api-gateway</artifactId>

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>api-gateway</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -22,7 +22,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>async-method-invocation</artifactId>
<dependencies>

View File

@ -20,7 +20,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -22,7 +22,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>bridge</artifactId>
<dependencies>

View File

@ -9,36 +9,47 @@ tags:
---
## Intent
Separate the construction of a complex object from its
representation so that the same construction process can create different
representations.
Separate the construction of a complex object from its representation so that the same construction
process can create different representations.
## Explanation
Real world example
> Imagine a character generator for a role playing game. The easiest option is to let computer create the character for you. But if you want to select the character details like profession, gender, hair color etc. the character generation becomes a step-by-step process that completes when all the selections are ready.
> Imagine a character generator for a role-playing game. The easiest option is to let the computer
> create the character for you. If you want to manually select the character details like
> profession, gender, hair color etc. the character generation becomes a step-by-step process that
> completes when all the selections are ready.
In plain words
> Allows you to create different flavors of an object while avoiding constructor pollution. Useful when there could be several flavors of an object. Or when there are a lot of steps involved in creation of an object.
> Allows you to create different flavors of an object while avoiding constructor pollution. Useful
> when there could be several flavors of an object. Or when there are a lot of steps involved in
> creation of an object.
Wikipedia says
> The builder pattern is an object creation software design pattern with the intentions of finding a solution to the telescoping constructor anti-pattern.
> The builder pattern is an object creation software design pattern with the intentions of finding
> a solution to the telescoping constructor anti-pattern.
Having said that let me add a bit about what telescoping constructor anti-pattern is. At one point or the other we have all seen a constructor like below:
Having said that let me add a bit about what telescoping constructor anti-pattern is. At one point
or the other, we have all seen a constructor like below:
```java
public Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) {
}
```
As you can see the number of constructor parameters can quickly get out of hand and it might become difficult to understand the arrangement of parameters. Plus this parameter list could keep on growing if you would want to add more options in future. This is called telescoping constructor anti-pattern.
As you can see the number of constructor parameters can quickly get out of hand, and it may become
difficult to understand the arrangement of parameters. Plus this parameter list could keep on
growing if you would want to add more options in the future. This is called telescoping constructor
anti-pattern.
**Programmatic Example**
The sane alternative is to use the Builder pattern. First of all we have our hero that we want to create
The sane alternative is to use the Builder pattern. First of all we have our hero that we want to
create:
```java
public final class Hero {
@ -60,7 +71,7 @@ public final class Hero {
}
```
And then we have the builder
Then we have the builder:
```java
public static class Builder {
@ -105,20 +116,22 @@ And then we have the builder
}
```
And then it can be used as:
Then it can be used as:
```java
var mage = new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();
```
## Class diagram
![alt text](./etc/builder.urm.png "Builder class diagram")
## Applicability
Use the Builder pattern when
* the algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled
* the construction process must allow different representations for the object that's constructed
* The algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled
* The construction process must allow different representations for the object that's constructed
## Real world examples

View File

@ -22,7 +22,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>builder</artifactId>
<dependencies>

View File

@ -22,7 +22,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>business-delegate</artifactId>
<dependencies>

View File

@ -20,7 +20,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>caching</artifactId>
<dependencies>

View File

@ -9,14 +9,16 @@ tags:
---
## Intent
Callback is a piece of executable code that is passed as an argument to other code, which is expected to call back
(execute) the argument at some convenient time.
Callback is a piece of executable code that is passed as an argument to other code, which is
expected to call back (execute) the argument at some convenient time.
## Explanation
Real world example
> We need to be notified after executing task has finished. We pass a callback method for the executor and wait for it to call back on us.
> We need to be notified after executing task has finished. We pass a callback method for
> the executor and wait for it to call back on us.
In plain words
@ -24,7 +26,9 @@ In plain words
Wikipedia says
> In computer programming, a callback, also known as a "call-after" function, is any executable code that is passed as an argument to other code; that other code is expected to call back (execute) the argument at a given time.
> In computer programming, a callback, also known as a "call-after" function, is any executable
> code that is passed as an argument to other code; that other code is expected to call
> back (execute) the argument at a given time.
**Programmatic Example**
@ -61,7 +65,7 @@ public final class SimpleTask extends Task {
}
```
Finally here's how we execute a task and receive a callback when it's finished.
Finally, here's how we execute a task and receive a callback when it's finished.
```java
var task = new SimpleTask();
@ -69,13 +73,15 @@ Finally here's how we execute a task and receive a callback when it's finished.
```
## Class diagram
![alt text](./etc/callback.png "Callback")
## Applicability
Use the Callback pattern when
* when some arbitrary synchronous or asynchronous action must be performed after execution of some defined activity.
## Real world examples
* [CyclicBarrier](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29) constructor can accept callback that will be triggered every time when barrier is tripped.
* [CyclicBarrier](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29) constructor can accept a callback that will be triggered every time a barrier is tripped.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -8,11 +8,6 @@ package com.iluwatar.callback {
interface Callback {
+ call() {abstract}
}
class LambdasApp {
- LOGGER : Logger {static}
- LambdasApp()
+ main(args : String[]) {static}
}
class SimpleTask {
- LOGGER : Logger {static}
+ SimpleTask()

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>callback</artifactId>
<dependencies>

View File

@ -9,27 +9,32 @@ tags:
---
## Intent
Avoid coupling the sender of a request to its receiver by giving
more than one object a chance to handle the request. Chain the receiving
objects and pass the request along the chain until an object handles it.
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to
handle the request. Chain the receiving objects and pass the request along the chain until an object
handles it.
## Explanation
Real world example
> The Orc King gives loud orders to his army. The closest one to react is the commander, then officer and then soldier. The commander, officer and soldier here form a chain of responsibility.
> The Orc King gives loud orders to his army. The closest one to react is the commander, then
> officer and then soldier. The commander, officer and soldier here form a chain of responsibility.
In plain words
> It helps building a chain of objects. Request enters from one end and keeps going from object to object till it finds the suitable handler.
> It helps to build a chain of objects. A request enters from one end and keeps going from an object
> to another until it finds a suitable handler.
Wikipedia says
> In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain.
> In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of
> a source of command objects and a series of processing objects. Each processing object contains
> logic that defines the types of command objects that it can handle; the rest are passed to the
> next processing object in the chain.
**Programmatic Example**
Translating our example with orcs from above. First we have the request class
Translating our example with the orcs from above. First we have the `Request` class:
```java
public class Request {
@ -140,14 +145,16 @@ king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); // Orc so
```
## Class diagram
![alt text](./etc/chain.urm.png "Chain of Responsibility class diagram")
## Applicability
Use Chain of Responsibility when
* more than one object may handle a request, and the handler isn't known a priori. The handler should be ascertained automatically
* you want to issue a request to one of several objects without specifying the receiver explicitly
* the set of objects that can handle a request should be specified dynamically
* More than one object may handle a request, and the handler isn't known a priori. The handler should be ascertained automatically.
* You want to issue a request to one of several objects without specifying the receiver explicitly.
* The set of objects that can handle a request should be specified dynamically.
## Real world examples

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>chain</artifactId>
<dependencies>

View File

@ -12,32 +12,43 @@ tags:
## Intent
Handle costly remote *procedure/service* calls in such a way that the failure of a **single** service/component cannot bring the whole application down, and we can reconnect to the service as soon as possible.
Handle costly remote service calls in such a way that the failure of a single service/component
cannot bring the whole application down, and we can reconnect to the service as soon as possible.
## Explanation
Real world example
> Imagine a Web App that has both local (example: files and images) and remote (example: database entries) to serve. The database might not be responding due to a variety of reasons, so if the application keeps trying to read from the database using multiple threads/processes, soon all of them will hang and our entire web application will crash. We should be able to detect this situation and show the user an appropriate message so that he/she can explore other parts of the app unaffected by the database failure without any problem.
> Imagine a web application that has both local files/images and remote database entries to serve.
> The database might not be responding due to a variety of reasons, so if the application keeps
> trying to read from the database using multiple threads/processes, soon all of them will hang
> causing our entire web application will crash. We should be able to detect this situation and show
> the user an appropriate message so that he/she can explore other parts of the app unaffected by
> the database failure.
In plain words
> Allows us to save resources when we know a remote service failed. Useful when all parts of our application are highly decoupled from each other, and failure of one component doesn't mean the other parts will stop working.
> Circuit Breaker allows graceful handling of failed remote services. It's especially useful when
> all parts of our application are highly decoupled from each other, and failure of one component
> doesn't mean the other parts will stop working.
Wikipedia says
> **Circuit breaker** is a design pattern used in modern software development. It is used to detect failures and encapsulates the logic of preventing a failure from constantly recurring, during maintenance, temporary external system failure or unexpected system difficulties.
So, how does this all come together?
> Circuit breaker is a design pattern used in modern software development. It is used to detect
> failures and encapsulates the logic of preventing a failure from constantly recurring, during
> maintenance, temporary external system failure or unexpected system difficulties.
## Programmatic Example
With the above example in mind we will imitate the functionality in a simple manner. We have two services: A *monitoring service* which will mimic the web app and will make both **local** and **remote** calls.
So, how does this all come together? With the above example in mind we will imitate the
functionality in a simple example. A monitoring service mimics the web app and makes both local and
remote calls.
The service architecture is as follows:
![alt text](./etc/ServiceDiagram.PNG "Service Diagram")
In terms of code, the End user application is:
In terms of code, the end user application is:
```java
public class App {
@ -62,7 +73,7 @@ public class App {
}
```
The monitoring service is:
The monitoring service:
``` java
public class MonitoringService {
@ -80,7 +91,8 @@ public class MonitoringService {
}
}
```
As it can be seen, it does the call to get local resources directly, but it wraps the call to remote (costly) service in a circuit breaker object, which prevents faults as follows:
As it can be seen, it does the call to get local resources directly, but it wraps the call to
remote (costly) service in a circuit breaker object, which prevents faults as follows:
```java
public class CircuitBreaker {
@ -155,24 +167,27 @@ public class CircuitBreaker {
}
```
How does the above pattern prevent failures? Let's understand via this finite state machine implemented by it.
How does the above pattern prevent failures? Let's understand via this finite state machine
implemented by it.
![alt text](./etc/StateDiagram.PNG "State Diagram")
- We initialize the Circuit Breaker object with certain parameters: **timeout**, **failureThreshold** and **retryTimePeriod** which help determine how resilient the API is.
- Initially, we are in the **closed** state and the remote call to API happens.
- We initialize the Circuit Breaker object with certain parameters: `timeout`, `failureThreshold` and `retryTimePeriod` which help determine how resilient the API is.
- Initially, we are in the `closed` state and nos remote calls to the API have occurred.
- Every time the call succeeds, we reset the state to as it was in the beginning.
- If the number of failures cross a certain threshold, we move to the **open** state, which acts just like an open circuit and prevents remote service calls from being made, thus saving resources. (Here, we return the response called ```stale response from API```)
- Once we exceed the retry timeout period, we move to the **half-open** state and make another call to the remote service again to check if the service is working so that we can serve fresh content. A *failure* sets it back to **open** state and another attempt is made after retry timeout period, while a *success* sets it to **closed** state so that everything starts working normally again.
- If the number of failures cross a certain threshold, we move to the `open` state, which acts just like an open circuit and prevents remote service calls from being made, thus saving resources. (Here, we return the response called ```stale response from API```)
- Once we exceed the retry timeout period, we move to the `half-open` state and make another call to the remote service again to check if the service is working so that we can serve fresh content. A failure sets it back to `open` state and another attempt is made after retry timeout period, while a success sets it to `closed` state so that everything starts working normally again.
## Class diagram
![alt text](./etc/circuit-breaker.urm.png "Circuit Breaker class diagram")
## Applicability
Use the Circuit Breaker pattern when
- Building a fault-tolerant application where failure of some services shouldn't bring the entire application down.
- Building an continuously incremental/continuous delivery application, as some of it's components can be upgraded without shutting it down entirely.
- Building a continuously running (always-on) application, so that its components can be upgraded without shutting it down entirely.
## Related Patterns

View File

@ -27,7 +27,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>circuit-breaker</artifactId>
<dependencies>

View File

@ -27,7 +27,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>collection-pipeline</artifactId>
<dependencies>

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>combinator</artifactId>

View File

@ -9,15 +9,20 @@ tags:
---
## Also known as
Action, Transaction
## Intent
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
Encapsulate a request as an object, thereby letting you parameterize clients with different
requests, queue or log requests, and support undoable operations.
## Explanation
Real world example
> There is a wizard casting spells on a goblin. The spells are executed on the goblin one by one. The first spell shrinks the goblin and the second makes him invisible. Then the wizard reverses the spells one by one. Each spell here is a command object that can be undone.
> There is a wizard casting spells on a goblin. The spells are executed on the goblin one by one.
> The first spell shrinks the goblin and the second makes him invisible. Then the wizard reverses
> the spells one by one. Each spell here is a command object that can be undone.
In plain words
@ -25,11 +30,13 @@ In plain words
Wikipedia says
> In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time.
> In object-oriented programming, the command pattern is a behavioral design pattern in which an
> object is used to encapsulate all information needed to perform an action or trigger an event at
> a later time.
**Programmatic Example**
Here's the sample code with wizard and goblin. Let's start from the wizard class.
Here's the sample code with wizard and goblin. Let's start from the `Wizard` class.
```java
public class Wizard {
@ -149,7 +156,7 @@ public class ShrinkSpell implements Command {
}
```
And last we have the goblin who's the target of the spells.
Finally, we have the goblin who's the target of the spells.
```java
public abstract class Target {
@ -199,44 +206,67 @@ public class Goblin extends Target {
}
```
Finally here's the whole example in action.
Here's the whole example in action.
```java
var wizard = new Wizard();
var goblin = new Goblin();
goblin.printStatus();
// Goblin, [size=normal] [visibility=visible]
wizard.castSpell(new ShrinkSpell(), goblin);
// Wizard casts Shrink spell at Goblin
goblin.printStatus();
// Goblin, [size=small] [visibility=visible]
wizard.castSpell(new InvisibilitySpell(), goblin);
// Wizard casts Invisibility spell at Goblin
goblin.printStatus();
// Goblin, [size=small] [visibility=invisible]
wizard.undoLastSpell();
// Wizard undoes Invisibility spell
goblin.printStatus();
```
Here's the program output:
```java
// Goblin, [size=normal] [visibility=visible]
// Wizard casts Shrink spell at Goblin
// Goblin, [size=small] [visibility=visible]
// Wizard casts Invisibility spell at Goblin
// Goblin, [size=small] [visibility=invisible]
// Wizard undoes Invisibility spell
// Goblin, [size=small] [visibility=visible]
```
## Class diagram
![alt text](./etc/command.png "Command")
## Applicability
Use the Command pattern when you want to
* parameterize objects by an action to perform. You can express such parameterization in a procedural language with a callback function, that is, a function that's registered somewhere to be called at a later point. Commands are an object-oriented replacement for callbacks.
* specify, queue, and execute requests at different times. A Command object can have a lifetime independent of the original request. If the receiver of a request can be represented in an address space-independent way, then you can transfer a command object for the request to a different process and fulfill the request there
* support undo. The Command's execute operation can store state for reversing its effects in the command itself. The Command interface must have an added Unexecute operation that reverses the effects of a previous call to execute. Executed commands are stored in a history list. Unlimited-level undo and redo is achieved by traversing this list backwards and forwards calling unexecute and execute, respectively
* support logging changes so that they can be reapplied in case of a system crash. By augmenting the Command interface with load and store operations, you can keep a persistent log of changes. Recovering from a crash involves reloading logged commands from disk and re-executing them with the execute operation
* structure a system around high-level operations build on primitive operations. Such a structure is common in information systems that support transactions. A transaction encapsulates a set of changes to data. The Command pattern offers a way to model transactions. Commands have a common interface, letting you invoke all transactions the same way. The pattern also makes it easy to extend the system with new transactions
Use the Command pattern when you want to:
* Parameterize objects by an action to perform. You can express such parameterization in a
procedural language with a callback function, that is, a function that's registered somewhere to be
called at a later point. Commands are an object-oriented replacement for callbacks.
* Specify, queue, and execute requests at different times. A Command object can have a lifetime
independent of the original request. If the receiver of a request can be represented in an address
space-independent way, then you can transfer a command object for the request to a different process
and fulfill the request there.
* Support undo. The Command's execute operation can store state for reversing its effects in the
command itself. The Command interface must have an added un-execute operation that reverses the
effects of a previous call to execute. The executed commands are stored in a history list.
Unlimited-level undo and redo is achieved by traversing this list backwards and forwards calling
un-execute and execute, respectively.
* Support logging changes so that they can be reapplied in case of a system crash. By augmenting the
Command interface with load and store operations, you can keep a persistent log of changes.
Recovering from a crash involves reloading logged commands from disk and re-executing them with
the execute operation.
* Structure a system around high-level operations build on primitive operations. Such a structure is
common in information systems that support transactions. A transaction encapsulates a set of changes
to data. The Command pattern offers a way to model transactions. Commands have a common interface,
letting you invoke all transactions the same way. The pattern also makes it easy to extend the
system with new transactions.
## Typical Use Case
* to keep a history of requests
* implement callback functionality
* implement the undo functionality
* To keep a history of requests
* Implement callback functionality
* Implement the undo functionality
## Real world examples

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>command</artifactId>
<dependencies>

View File

@ -27,7 +27,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>commander</artifactId>
<dependencies>

View File

@ -9,15 +9,17 @@ tags:
---
## Intent
Compose objects into tree structures to represent part-whole
hierarchies. Composite lets clients treat individual objects and compositions
of objects uniformly.
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients
treat individual objects and compositions of objects uniformly.
## Explanation
Real world example
> Every sentence is composed of words which are in turn composed of characters. Each of these objects is printable and they can have something printed before or after them like sentence always ends with full stop and word always has space before it
> Every sentence is composed of words which are in turn composed of characters. Each of these
> objects is printable and they can have something printed before or after them like sentence always
> ends with full stop and word always has space before it.
In plain words
@ -25,11 +27,16 @@ In plain words
Wikipedia says
> In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes that a group of objects is to be treated in the same way as a single instance of an object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.
> In software engineering, the composite pattern is a partitioning design pattern. The composite
> pattern describes that a group of objects is to be treated in the same way as a single instance of
> an object. The intent of a composite is to "compose" objects into tree structures to represent
> part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects
> and compositions uniformly.
**Programmatic Example**
Taking our sentence example from above. Here we have the base class and different printable types
Taking our sentence example from above. Here we have the base class `LetterComposite` and the
different printable types `Letter`, `Word` and `Sentence`.
```java
public abstract class LetterComposite {
@ -102,7 +109,7 @@ public class Sentence extends LetterComposite {
}
```
Then we have a messenger to carry messages
Then we have a messenger to carry messages:
```java
public class Messenger {
@ -143,7 +150,7 @@ public class Messenger {
}
```
And then it can be used as
And then it can be used as:
```java
var orcMessage = new Messenger().messageFromOrcs();
@ -153,13 +160,16 @@ elfMessage.print(); // Much wind pours from your mouth.
```
## Class diagram
![alt text](./etc/composite.urm.png "Composite class diagram")
## Applicability
Use the Composite pattern when
* you want to represent part-whole hierarchies of objects
* you want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly
* You want to represent part-whole hierarchies of objects.
* You want clients to be able to ignore the difference between compositions of objects and
individual objects. Clients will treat all objects in the composite structure uniformly.
## Real world examples

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>composite</artifactId>
<dependencies>

View File

@ -9,16 +9,19 @@ tags:
---
## Intent
The purpose of the Converter Pattern is to provide a generic, common way of bidirectional
The purpose of the Converter pattern is to provide a generic, common way of bidirectional
conversion between corresponding types, allowing a clean implementation in which the types do not
need to be aware of each other. Moreover, the Converter Pattern introduces bidirectional collection
need to be aware of each other. Moreover, the Converter pattern introduces bidirectional collection
mapping, reducing a boilerplate code to minimum.
## Explanation
Real world example
> In real world applications it is often the case that database layer consists of entities that need to be mapped into DTOs for use on the business logic layer. Similar mapping is done for potentially huge amount of classes and we need a generic way to achieve this.
> In real world applications it is often the case that database layer consists of entities that need
> to be mapped into DTOs for use on the business logic layer. Similar mapping is done for
> potentially huge amount of classes and we need a generic way to achieve this.
In plain words
@ -26,7 +29,8 @@ In plain words
**Programmatic Example**
We need a generic solution for the mapping problem. To achieve this, let's introduce a generic converter.
We need a generic solution for the mapping problem. To achieve this, let's introduce a generic
converter.
```java
public class Converter<T, U> {
@ -77,7 +81,7 @@ public class UserConverter extends Converter<UserDto, User> {
}
```
Now mapping between User and UserDto becomes trivial.
Now mapping between `User` and `UserDto` becomes trivial.
```java
var userConverter = new UserConverter();
@ -86,14 +90,18 @@ var user = userConverter.convertFromDto(dtoUser);
```
## Class diagram
![alt text](./etc/converter.png "Converter Pattern")
## Applicability
Use the Converter Pattern in the following situations:
* When you have types that logically correspond which other and you need to convert entities between them
* When you want to provide different ways of types conversions depending on a context
* Whenever you introduce a DTO (Data transfer object), you will probably need to convert it into the domain equivalence
* When you have types that logically correspond with each other and you need to convert entities
between them.
* When you want to provide different ways of types conversions depending on the context.
* Whenever you introduce a DTO (Data transfer object), you will probably need to convert it into the
domain equivalence.
## Credits

View File

@ -20,7 +20,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>converter</artifactId>
<modelVersion>4.0.0</modelVersion>

View File

@ -30,7 +30,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>cqrs</artifactId>
<dependencies>

View File

@ -9,13 +9,15 @@ tags:
---
## Intent
Object provides an abstract interface to some type of database or other persistence mechanism.
## Explanation
Real world example
> There's a set of customers that need to be persisted to database. Additionally we need the whole set of CRUD (create/read/update/delete) operations so we can operate on customers easily.
> There's a set of customers that need to be persisted to database. Additionally we need the whole
> set of CRUD (create/read/update/delete) operations so we can operate on customers easily.
In plain words
@ -23,11 +25,12 @@ In plain words
Wikipedia says
> In computer software, a data access object (DAO) is a pattern that provides an abstract interface to some type of database or other persistence mechanism.
> In computer software, a data access object (DAO) is a pattern that provides an abstract interface
> to some type of database or other persistence mechanism.
**Programmatic Example**
Walking through our customers example, here's the basic Customer entity.
Walking through our customers example, here's the basic `Customer` entity.
```java
public class Customer {
@ -41,60 +44,13 @@ public class Customer {
this.firstName = firstName;
this.lastName = lastName;
}
public int getId() {
return id;
}
public void setId(final int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "Customer{" + "id=" + getId() + ", firstName='" + getFirstName() + '\'' + ", lastName='"
+ getLastName() + '\'' + '}';
}
@Override
public boolean equals(final Object that) {
var isEqual = false;
if (this == that) {
isEqual = true;
} else if (that != null && getClass() == that.getClass()) {
final var customer = (Customer) that;
if (getId() == customer.getId()) {
isEqual = true;
}
}
return isEqual;
}
@Override
public int hashCode() {
return getId();
}
// getters and setters ->
...
}
```
Here's the DAO interface and two different implementations for it. InMemoryCustomerDao keeps a simple map of customers
in memory while DBCustomerDao is the real RDBMS implementation.
Here's the `CustomerDao` interface and two different implementations for it. `InMemoryCustomerDao`
keeps a simple map of customers in memory while `DBCustomerDao` is the real RDBMS implementation.
```java
public interface CustomerDao {
@ -114,35 +70,8 @@ public class InMemoryCustomerDao implements CustomerDao {
private final Map<Integer, Customer> idToCustomer = new HashMap<>();
@Override
public Stream<Customer> getAll() {
return idToCustomer.values().stream();
}
@Override
public Optional<Customer> getById(final int id) {
return Optional.ofNullable(idToCustomer.get(id));
}
@Override
public boolean add(final Customer customer) {
if (getById(customer.getId()).isPresent()) {
return false;
}
idToCustomer.put(customer.getId(), customer);
return true;
}
@Override
public boolean update(final Customer customer) {
return idToCustomer.replace(customer.getId(), customer) != null;
}
@Override
public boolean delete(final Customer customer) {
return idToCustomer.remove(customer.getId()) != null;
}
// implement the interface using the map
...
}
public class DbCustomerDao implements CustomerDao {
@ -155,121 +84,8 @@ public class DbCustomerDao implements CustomerDao {
this.dataSource = dataSource;
}
@Override
public Stream<Customer> getAll() throws Exception {
try {
var connection = getConnection();
var statement = connection.prepareStatement("SELECT * FROM CUSTOMERS");
var resultSet = statement.executeQuery();
return StreamSupport.stream(new Spliterators.AbstractSpliterator<Customer>(Long.MAX_VALUE,
Spliterator.ORDERED) {
@Override
public boolean tryAdvance(Consumer<? super Customer> action) {
try {
if (!resultSet.next()) {
return false;
}
action.accept(createCustomer(resultSet));
return true;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}, false).onClose(() -> mutedClose(connection, statement, resultSet));
} catch (SQLException e) {
throw new CustomException(e.getMessage(), e);
}
}
private Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
private void mutedClose(Connection connection, PreparedStatement statement, ResultSet resultSet) {
try {
resultSet.close();
statement.close();
connection.close();
} catch (SQLException e) {
LOGGER.info("Exception thrown " + e.getMessage());
}
}
private Customer createCustomer(ResultSet resultSet) throws SQLException {
return new Customer(resultSet.getInt("ID"),
resultSet.getString("FNAME"),
resultSet.getString("LNAME"));
}
@Override
public Optional<Customer> getById(int id) throws Exception {
ResultSet resultSet = null;
try (var connection = getConnection();
var statement = connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) {
statement.setInt(1, id);
resultSet = statement.executeQuery();
if (resultSet.next()) {
return Optional.of(createCustomer(resultSet));
} else {
return Optional.empty();
}
} catch (SQLException ex) {
throw new CustomException(ex.getMessage(), ex);
} finally {
if (resultSet != null) {
resultSet.close();
}
}
}
@Override
public boolean add(Customer customer) throws Exception {
if (getById(customer.getId()).isPresent()) {
return false;
}
try (var connection = getConnection();
var statement = connection.prepareStatement("INSERT INTO CUSTOMERS VALUES (?,?,?)")) {
statement.setInt(1, customer.getId());
statement.setString(2, customer.getFirstName());
statement.setString(3, customer.getLastName());
statement.execute();
return true;
} catch (SQLException ex) {
throw new CustomException(ex.getMessage(), ex);
}
}
@Override
public boolean update(Customer customer) throws Exception {
try (var connection = getConnection();
var statement =
connection
.prepareStatement("UPDATE CUSTOMERS SET FNAME = ?, LNAME = ? WHERE ID = ?")) {
statement.setString(1, customer.getFirstName());
statement.setString(2, customer.getLastName());
statement.setInt(3, customer.getId());
return statement.executeUpdate() > 0;
} catch (SQLException ex) {
throw new CustomException(ex.getMessage(), ex);
}
}
@Override
public boolean delete(Customer customer) throws Exception {
try (var connection = getConnection();
var statement = connection.prepareStatement("DELETE FROM CUSTOMERS WHERE ID = ?")) {
statement.setInt(1, customer.getId());
return statement.executeUpdate() > 0;
} catch (SQLException ex) {
throw new CustomException(ex.getMessage(), ex);
}
}
}
// implement the interface using the data source
...
```
Finally here's how we use our DAO to manage customers.
@ -301,15 +117,45 @@ Finally here's how we use our DAO to manage customers.
deleteSchema(dataSource);
```
The program output:
```java
customerDao.getAllCustomers():
Customer{id=1, firstName='Adam', lastName='Adamson'}
Customer{id=2, firstName='Bob', lastName='Bobson'}
Customer{id=3, firstName='Carl', lastName='Carlson'}
customerDao.getCustomerById(2): Optional[Customer{id=2, firstName='Bob', lastName='Bobson'}]
customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@7cef4e59
customerDao.getAllCustomers():
Customer{id=1, firstName='Adam', lastName='Adamson'}
Customer{id=2, firstName='Bob', lastName='Bobson'}
Customer{id=3, firstName='Carl', lastName='Carlson'}
Customer{id=4, firstName='Daniel', lastName='Danielson'}
customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@2db0f6b2
customerDao.getAllCustomers():
Customer{id=1, firstName='Adam', lastName='Adamson'}
Customer{id=2, firstName='Bob', lastName='Bobson'}
Customer{id=3, firstName='Carl', lastName='Carlson'}
customerDao.getCustomerById(2): Optional[Customer{id=2, firstName='Bob', lastName='Bobson'}]
customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@12c8a2c0
customerDao.getAllCustomers():
Customer{id=1, firstName='Adam', lastName='Adamson'}
Customer{id=2, firstName='Bob', lastName='Bobson'}
Customer{id=3, firstName='Carl', lastName='Carlson'}
Customer{id=4, firstName='Daniel', lastName='Danielson'}
customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@6ec8211c
```
## Class diagram
![alt text](./etc/dao.png "Data Access Object")
## Applicability
Use the Data Access Object in any of the following situations
* when you want to consolidate how the data layer is accessed
* when you want to avoid writing multiple data retrieval/persistence layers
Use the Data Access Object in any of the following situations:
* When you want to consolidate how the data layer is accessed.
* When you want to avoid writing multiple data retrieval/persistence layers.
## Credits

View File

@ -30,7 +30,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>dao</artifactId>

View File

@ -33,7 +33,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>data-bus</artifactId>
<dependencies>

View File

@ -30,7 +30,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>data-locality</artifactId>

View File

@ -28,7 +28,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>data-mapper</artifactId>
<dependencies>

View File

@ -9,13 +9,16 @@ tags:
---
## Intent
Pass data with multiple attributes in one shot from client to server, to avoid multiple calls to remote server.
Pass data with multiple attributes in one shot from client to server, to avoid multiple calls to
remote server.
## Explanation
Real world example
> We need to fetch information about customers from remote database. Instead of querying the attributes one at a time, we use DTOs to transfer all the relevant attributes in a single shot.
> We need to fetch information about customers from remote database. Instead of querying the
> attributes one at a time, we use DTOs to transfer all the relevant attributes in a single shot.
In plain words
@ -23,16 +26,17 @@ In plain words
Wikipedia says
> In the field of programming a data transfer object (DTO) is an object that carries data between processes. The
motivation for its use is that communication between processes is usually done resorting to remote interfaces
(e.g., web services), where each call is an expensive operation. Because the majority of the cost of each call is
related to the round-trip time between the client and the server, one way of reducing the number of calls is to use an
object (the DTO) that aggregates the data that would have been transferred by the several calls, but that is served by
one call only.
> In the field of programming a data transfer object (DTO) is an object that carries data between
> processes. The motivation for its use is that communication between processes is usually done
> resorting to remote interfaces (e.g. web services), where each call is an expensive operation.
> Because the majority of the cost of each call is related to the round-trip time between the client
> and the server, one way of reducing the number of calls is to use an object (the DTO) that
> aggregates the data that would have been transferred by the several calls, but that is served by
> one call only.
**Programmatic Example**
Let's first introduce our simple customer DTO class.
Let's first introduce our simple `CustomerDTO` class.
```java
public class CustomerDto {
@ -60,7 +64,7 @@ public class CustomerDto {
}
```
Customer resource class acts as the server for customer information.
`CustomerResource` class acts as the server for customer information.
```java
public class CustomerResource {
@ -94,10 +98,12 @@ Now fetching customer information is easy since we have the DTOs.
```
## Class diagram
![alt text](./etc/data-transfer-object.urm.png "data-transfer-object")
## Applicability
Use the Data Transfer Object pattern when
Use the Data Transfer Object pattern when:
* The client is asking for multiple information. And the information is related.
* When you want to boost the performance to get resources.

View File

@ -28,7 +28,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>data-transfer-object</artifactId>
<dependencies>

View File

@ -10,30 +10,39 @@ tags:
---
## Also known as
Wrapper
## Intent
Attach additional responsibilities to an object dynamically.
Decorators provide a flexible alternative to subclassing for extending
functionality.
Attach additional responsibilities to an object dynamically. Decorators provide a flexible
alternative to subclassing for extending functionality.
## Explanation
Real world example
> There is an angry troll living in the nearby hills. Usually it goes bare handed but sometimes it has a weapon. To arm the troll it's not necessary to create a new troll but to decorate it dynamically with a suitable weapon.
> There is an angry troll living in the nearby hills. Usually it goes bare handed but sometimes it
> has a weapon. To arm the troll it's not necessary to create a new troll but to decorate it
> dynamically with a suitable weapon.
In plain words
> Decorator pattern lets you dynamically change the behavior of an object at run time by wrapping them in an object of a decorator class.
> Decorator pattern lets you dynamically change the behavior of an object at run time by wrapping
> them in an object of a decorator class.
Wikipedia says
> In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern.
> In object-oriented programming, the decorator pattern is a design pattern that allows behavior to
> be added to an individual object, either statically or dynamically, without affecting the behavior
> of other objects from the same class. The decorator pattern is often useful for adhering to the
> Single Responsibility Principle, as it allows functionality to be divided between classes with
> unique areas of concern.
**Programmatic Example**
Let's take the troll example. First of all we have a simple troll implementing the troll interface
Let's take the troll example. First of all we have a `SimpleTroll` implementing the `Troll`
interface:
```java
public interface Troll {
@ -63,7 +72,7 @@ public class SimpleTroll implements Troll {
}
```
Next we want to add club for the troll. We can do it dynamically by using a decorator
Next we want to add club for the troll. We can do it dynamically by using a decorator:
```java
public class ClubbedTroll implements Troll {
@ -94,7 +103,7 @@ public class ClubbedTroll implements Troll {
}
```
Here's the troll in action
Here's the troll in action:
```java
// simple troll
@ -108,20 +117,36 @@ clubbedTroll.attack(); // The troll tries to grab you! The troll swings at you w
clubbedTroll.fleeBattle(); // The troll shrieks in horror and runs away!
```
Program output:
```java
The troll tries to grab you!
The troll shrieks in horror and runs away!
The troll tries to grab you! The troll swings at you with a club!
The troll shrieks in horror and runs away!
```
## Class diagram
![alt text](./etc/decorator.urm.png "Decorator pattern class diagram")
## Applicability
Use Decorator
* To add responsibilities to individual objects dynamically and transparently, that is, without affecting other objects
* For responsibilities that can be withdrawn
* When extension by subclassing is impractical. Sometimes a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination. Or a class definition may be hidden or otherwise unavailable for subclassing
Decorator is used to:
* Add responsibilities to individual objects dynamically and transparently, that is, without
affecting other objects.
* For responsibilities that can be withdrawn.
* When extension by subclassing is impractical. Sometimes a large number of independent extensions
are possible and would produce an explosion of subclasses to support every combination. Or a class
definition may be hidden or otherwise unavailable for subclassing.
## Tutorial
* [Decorator Pattern Tutorial](https://www.journaldev.com/1540/decorator-design-pattern-in-java-example)
## Real world examples
* [java.io.InputStream](http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html), [java.io.OutputStream](http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html),
[java.io.Reader](http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html) and [java.io.Writer](http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html)
* [java.util.Collections#synchronizedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedCollection-java.util.Collection-)

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>decorator</artifactId>
<dependencies>

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -9,15 +9,19 @@ tags:
---
## Intent
Dependency Injection is a software design pattern in which one or more dependencies (or services) are injected, or
passed by reference, into a dependent object (or client) and are made part of the client's state. The pattern separates
the creation of a client's dependencies from its own behavior, which allows program designs to be loosely coupled and
to follow the inversion of control and single responsibility principles.
Dependency Injection is a software design pattern in which one or more dependencies (or services)
are injected, or passed by reference, into a dependent object (or client) and are made part of the
client's state. The pattern separates the creation of a client's dependencies from its own behavior,
which allows program designs to be loosely coupled and to follow the inversion of control and single
responsibility principles.
## Explanation
Real world example
> The old wizard likes to fill his pipe and smoke tobacco once in a while. However, he doesn't want to depend on a single tobacco brand only but likes to be able to enjoy them all interchangeably.
> The old wizard likes to fill his pipe and smoke tobacco once in a while. However, he doesn't want
> to depend on a single tobacco brand only but likes to be able to enjoy them all interchangeably.
In plain words
@ -25,11 +29,12 @@ In plain words
Wikipedia says
> In software engineering, dependency injection is a technique in which an object receives other objects that it depends on. These other objects are called dependencies.
> In software engineering, dependency injection is a technique in which an object receives other
> objects that it depends on. These other objects are called dependencies.
**Programmatic Example**
Let's first introduce the tobacco brands.
Let's first introduce the `Tobacco` interface and the concrete brands.
```java
public abstract class Tobacco {
@ -52,7 +57,7 @@ public class OldTobyTobacco extends Tobacco {
}
```
Next here's the wizard class hierarchy.
Next here's the `Wizard` class hierarchy.
```java
public interface Wizard {
@ -83,13 +88,15 @@ And lastly we can show how easy it is to give the old wizard any brand of tobacc
```
## Class diagram
![alt text](./etc/dependency-injection.png "Dependency Injection")
## Applicability
Use the Dependency Injection pattern when
* When you need to remove knowledge of concrete implementation from object
* To enable unit testing of classes in isolation using mock objects or stubs
Use the Dependency Injection pattern when:
* When you need to remove knowledge of concrete implementation from object.
* To enable unit testing of classes in isolation using mock objects or stubs.
## Credits

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>dependency-injection</artifactId>
<dependencies>

View File

@ -29,10 +29,10 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>dirty-flag</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
<name>dirty-flag</name>
<url>http://maven.apache.org</url>
<properties>

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -27,7 +27,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>double-checked-locking</artifactId>
<dependencies>

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>double-dispatch</artifactId>
<dependencies>

View File

@ -31,7 +31,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<dependencies>

View File

@ -30,7 +30,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>eip-message-channel</artifactId>
<dependencies>

View File

@ -28,7 +28,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>eip-publish-subscribe</artifactId>
<dependencies>

View File

@ -31,7 +31,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<dependencies>

View File

@ -31,7 +31,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<dependencies>

View File

@ -28,7 +28,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>event-aggregator</artifactId>
<dependencies>

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>event-asynchronous</artifactId>
<dependencies>

View File

@ -31,7 +31,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>event-driven-architecture</artifactId>

View File

@ -30,7 +30,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>event-queue</artifactId>
<dependencies>

View File

@ -30,7 +30,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>event-sourcing</artifactId>
<dependencies>

View File

@ -9,15 +9,18 @@ tags:
---
## Intent
Execute Around idiom frees the user from certain actions that should always be executed before and after the business
method. A good example of this is resource allocation and deallocation leaving the user to specify only what to do with
the resource.
Execute Around idiom frees the user from certain actions that should always be executed before and
after the business method. A good example of this is resource allocation and deallocation leaving
the user to specify only what to do with the resource.
## Explanation
Real world example
> We need to provide a class that can be used to write text strings to files. To make it easy for the user we let our service class open and close the file automatically, the user only has to specify what is written into which file.
> We need to provide a class that can be used to write text strings to files. To make it easy for
> the user we let our service class open and close the file automatically, the user only has to
> specify what is written into which file.
In plain words
@ -25,7 +28,9 @@ In plain words
[Stack Overflow](https://stackoverflow.com/questions/341971/what-is-the-execute-around-idiom) says
> Basically it's the pattern where you write a method to do things which are always required, e.g. resource allocation and clean-up, and make the caller pass in "what we want to do with the resource".
> Basically it's the pattern where you write a method to do things which are always required, e.g.
> resource allocation and clean-up, and make the caller pass in "what we want to do with the
> resource".
**Programmatic Example**
@ -61,12 +66,15 @@ To utilize the file writer the following code is needed.
```
## Class diagram
![alt text](./etc/execute-around.png "Execute Around")
## Applicability
Use the Execute Around idiom when
* you use an API that requires methods to be called in pairs such as open/close or allocate/deallocate.
* You use an API that requires methods to be called in pairs such as open/close or
allocate/deallocate.
## Credits

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>execute-around</artifactId>
<dependencies>

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -10,14 +10,18 @@ tags:
---
## Intent
Provide a unified interface to a set of interfaces in a subsystem.
Facade defines a higher-level interface that makes the subsystem easier to use.
Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level
interface that makes the subsystem easier to use.
## Explanation
Real world example
> How does a goldmine work? "Well, the miners go down there and dig gold!" you say. That is what you believe because you are using a simple interface that goldmine provides on the outside, internally it has to do a lot of stuff to make it happen. This simple interface to the complex subsystem is a facade.
> How does a goldmine work? "Well, the miners go down there and dig gold!" you say. That is what you
> believe because you are using a simple interface that goldmine provides on the outside, internally
> it has to do a lot of stuff to make it happen. This simple interface to the complex subsystem is a
> facade.
In plain words
@ -25,11 +29,13 @@ In plain words
Wikipedia says
> A facade is an object that provides a simplified interface to a larger body of code, such as a class library.
> A facade is an object that provides a simplified interface to a larger body of code, such as a
> class library.
**Programmatic Example**
Taking our goldmine example from above. Here we have the dwarven mine worker hierarchy
Let's take our goldmine example from above. Here we have the dwarven mine worker hierarchy. First
there's a base class `DwarvenMineWorker`:
```java
public abstract class DwarvenMineWorker {
@ -87,7 +93,12 @@ public abstract class DwarvenMineWorker {
GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK
}
}
```
Then we have the concrete dwarf classes `DwarvenTunnelDigger`, `DwarvenGoldDigger` and
`DwarvenCartOperator`:
```java
public class DwarvenTunnelDigger extends DwarvenMineWorker {
private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenTunnelDigger.class);
@ -135,7 +146,7 @@ public class DwarvenCartOperator extends DwarvenMineWorker {
```
To operate all these goldmine workers we have the facade
To operate all these goldmine workers we have the `DwarvenGoldmineFacade`:
```java
public class DwarvenGoldmineFacade {
@ -168,22 +179,27 @@ public class DwarvenGoldmineFacade {
}
```
Now to use the facade
Now let's use the facade:
```java
DwarvenGoldmineFacade facade = new DwarvenGoldmineFacade();
var facade = new DwarvenGoldmineFacade();
facade.startNewDay();
facade.digOutGold();
facade.endDay();
```
Program output:
```java
// Dwarf gold digger wakes up.
// Dwarf gold digger goes to the mine.
// Dwarf cart operator wakes up.
// Dwarf cart operator goes to the mine.
// Dwarven tunnel digger wakes up.
// Dwarven tunnel digger goes to the mine.
facade.digOutGold();
// Dwarf gold digger digs for gold.
// Dwarf cart operator moves gold chunks out of the mine.
// Dwarven tunnel digger creates another promising tunnel.
facade.endDay();
// Dwarf gold digger goes home.
// Dwarf gold digger goes to sleep.
// Dwarf cart operator goes home.
@ -193,14 +209,25 @@ facade.endDay();
```
## Class diagram
![alt text](./etc/facade.urm.png "Facade pattern class diagram")
## Applicability
Use the Facade pattern when
* you want to provide a simple interface to a complex subsystem. Subsystems often get more complex as they evolve. Most patterns, when applied, result in more and smaller classes. This makes the subsystem more reusable and easier to customize, but it also becomes harder to use for clients that don't need to customize it. A facade can provide a simple default view of the subsystem that is good enough for most clients. Only clients needing more customizability will need to look beyond the facade.
* there are many dependencies between clients and the implementation classes of an abstraction. Introduce a facade to decouple the subsystem from clients and other subsystems, thereby promoting subsystem independence and portability.
* you want to layer your subsystems. Use a facade to define an entry point to each subsystem level. If subsystems are dependent, then you can simplify the dependencies between them by making them communicate with each other solely through their facades.
* You want to provide a simple interface to a complex subsystem. Subsystems often get more complex
as they evolve. Most patterns, when applied, result in more and smaller classes. This makes the
subsystem more reusable and easier to customize, but it also becomes harder to use for clients that
don't need to customize it. A facade can provide a simple default view of the subsystem that is good
enough for most clients. Only clients needing more customization will need to look beyond the
facade.
* There are many dependencies between clients and the implementation classes of an abstraction.
Introduce a facade to decouple the subsystem from clients and other subsystems, thereby promoting
subsystem independence and portability.
* You want to layer your subsystems. Use a facade to define an entry point to each subsystem level.
If subsystems are dependent, then you can simplify the dependencies between them by making them
communicate with each other solely through their facades.
## Credits

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>facade</artifactId>
<dependencies>

View File

@ -30,7 +30,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>factory-kit</artifactId>
<dependencies>

View File

@ -10,17 +10,20 @@ tags:
---
## Also known as
Virtual Constructor
## Intent
Define an interface for creating an object, but let subclasses
decide which class to instantiate. Factory Method lets a class defer
instantiation to subclasses.
Define an interface for creating an object, but let subclasses decide which class to instantiate.
Factory Method lets a class defer instantiation to subclasses.
## Explanation
Real world example
> Blacksmith manufactures weapons. Elves require Elvish weapons and orcs require Orcish weapons. Depending on the customer at hand the right type of blacksmith is summoned.
> Blacksmith manufactures weapons. Elves require Elvish weapons and orcs require Orcish weapons.
> Depending on the customer at hand the right type of blacksmith is summoned.
In plain words
@ -28,11 +31,16 @@ In plain words
Wikipedia says
> In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.
> In class-based programming, the factory method pattern is a creational pattern that uses factory
> methods to deal with the problem of creating objects without having to specify the exact class of
> the object that will be created. This is done by creating objects by calling a factory method
> — either specified in an interface and implemented by child classes, or implemented in a base
> class and optionally overridden by derived classes—rather than by calling a constructor.
**Programmatic Example**
Taking our blacksmith example above. First of all we have a blacksmith interface and some implementations for it
Taking our blacksmith example above. First of all we have a `Blacksmith` interface and some
implementations for it:
```java
public interface Blacksmith {
@ -52,24 +60,33 @@ public class OrcBlacksmith implements Blacksmith {
}
```
Now as the customers come the correct type of blacksmith is summoned and requested weapons are manufactured
When the customers come, the correct type of blacksmith is summoned and requested weapons are
manufactured:
```java
var blacksmith = new ElfBlacksmith();
blacksmith.manufactureWeapon(WeaponType.SPEAR);
blacksmith.manufactureWeapon(WeaponType.AXE);
// Elvish weapons are created
```
Program output:
```java
// Elven spear
// Elven axe
```
## Class diagram
![alt text](./etc/factory-method.urm.png "Factory Method pattern class diagram")
## Applicability
Use the Factory Method pattern when
* a class can't anticipate the class of objects it must create
* a class wants its subclasses to specify the objects it creates
* classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate
Use the Factory Method pattern when:
* Class cannot anticipate the class of objects it must create.
* Class wants its subclasses to specify the objects it creates.
* Classes delegate responsibility to one of several helper subclasses, and you want to localize the
knowledge of which helper subclass is the delegate.
## Real world examples

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>factory-method</artifactId>
<dependencies>

133
factory/README.md Normal file
View File

@ -0,0 +1,133 @@
---
layout: pattern
title: Factory
folder: factory
permalink: /patterns/factory/
categories: Creational
tags:
- Gang of Four
---
## Also known as
* Simple Factory
* Static Factory Method
## Intent
Providing a static method encapsulated in a class called factory, in order to hide the
implementation logic and makes client code focus on usage rather then initialization new objects.
## Explanation
Real world example
> Lets say we have a web application connected to SQLServer, but now we want to switch to Oracle. To
> do so without modifying existing source code, we need to implements Simple Factory pattern, in
> which a static method can be invoked to create connection to a given database.
Wikipedia says
> Factory is an object for creating other objects formally a factory is a function or method that
> returns objects of a varying prototype or class.
**Programmatic Example**
We have an interface `Car` and two implementations `Ford` and `Ferrari`.
```java
public interface Car {
String getDescription();
}
public class Ford implements Car {
static final String DESCRIPTION = "This is Ford.";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
public class Ferrari implements Car {
static final String DESCRIPTION = "This is Ferrari.";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
```
Enumeration above represents types of cars that we support (`Ford` and `Ferrari`).
```java
public enum CarType {
FORD(Ford::new),
FERRARI(Ferrari::new);
private final Supplier<Car> constructor;
CarType(Supplier<Car> constructor) {
this.constructor = constructor;
}
public Supplier<Car> getConstructor() {
return this.constructor;
}
}
```
Then we have the static method `getCar` to create car objects encapsulated in the factory class
`CarSimpleFactory`.
```java
public class CarsFactory {
public static Car getCar(CarType type) {
return type.getConstructor().get();
}
}
```
Now on the client code we can create different types of cars using the factory class.
```java
var car1 = CarsFactory.getCar(CarType.FORD);
var car2 = CarsFactory.getCar(CarType.FERRARI);
LOGGER.info(car1.getDescription());
LOGGER.info(car2.getDescription());;
```
Program output:
```java
This is Ford.
This Ferrari.
```
## Class Diagram
![alt text](./etc/factory.urm.png "Factory pattern class diagram")
## Applicability
Use the Simple Factory pattern when you only care about the creation of a object, not how to create
and manage it.
Pros
* Allows keeping all objects creation in one place and avoid of spreading 'new' key value across codebase.
* Allows to writs loosely coupled code. Some of its main advantages include better testability, easy-to-understand code, swappable components, scalability and isolated features.
Cons
* The code becomes more complicated than it should be.
## Related patterns
* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)
* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)
* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/)

BIN
factory/etc/factory.urm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,35 @@
@startuml
package com.iluwatar.factory {
class App {
- LOGGER : Logger {static}
+ App()
+ main(args : String[]) {static}
}
interface Car {
+ getDescription() : String {abstract}
}
class CarsFactory {
+ CarsFactory()
+ getCar(type : CarType) : Car {static}
}
~enum CarType {
+ FERRARI {static}
+ FORD {static}
+ valueOf(name : String) : CarType {static}
+ values() : CarType[] {static}
}
class Ferrari {
~ DESCRIPTION : String {static}
+ Ferrari()
+ getDescription() : String
}
class Ford {
~ DESCRIPTION : String {static}
+ Ford()
+ getDescription() : String
}
}
CarType ..+ CarsFactory
Ferrari ..|> Car
Ford ..|> Car
@enduml

43
factory/pom.xml Normal file
View File

@ -0,0 +1,43 @@
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>factory</artifactId>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Maven assembly plugin is invoked with default setting which we have
in parent pom and specifying the class having main method -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<configuration>
<archive>
<manifest>
<mainClass>com.iluwatar.factory.App</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -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.factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Factory is an object for creating other objects, it providing Providing a static method to
* create and return objects of varying classes, in order to hide the implementation logic
* and makes client code focus on usage rather then objects initialization and management.
*
* <p>In this example the CarFactory is the factory class and it provides a static method to
* create different cars.
*/
public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
/**
* Program main entry point.
*/
public static void main(String[] args) {
var car1 = CarsFactory.getCar(CarType.FORD);
var car2 = CarsFactory.getCar(CarType.FERRARI);
LOGGER.info(car1.getDescription());
LOGGER.info(car2.getDescription());
}
}

View File

@ -0,0 +1,10 @@
package com.iluwatar.factory;
/**
* Car interface.
*/
public interface Car {
String getDescription();
}

View File

@ -0,0 +1,22 @@
package com.iluwatar.factory;
import java.util.function.Supplier;
public enum CarType {
/**
* Enumeration for different types of cars.
*/
FORD(Ford::new),
FERRARI(Ferrari::new);
private final Supplier<Car> constructor;
CarType(Supplier<Car> constructor) {
this.constructor = constructor;
}
public Supplier<Car> getConstructor() {
return this.constructor;
}
}

View File

@ -0,0 +1,14 @@
package com.iluwatar.factory;
/**
* Factory of cars.
*/
public class CarsFactory {
/**
* Factory method takes as parameter a car type and initiate the appropriate class.
*/
public static Car getCar(CarType type) {
return type.getConstructor().get();
}
}

View File

@ -0,0 +1,14 @@
package com.iluwatar.factory;
/**
* Ferrari implementation.
*/
public class Ferrari implements Car {
static final String DESCRIPTION = "This is Ferrari.";
@Override
public String getDescription() {
return DESCRIPTION;
}
}

View File

@ -0,0 +1,14 @@
package com.iluwatar.factory;
/**
* Ford implementation.
*/
public class Ford implements Car {
static final String DESCRIPTION = "This is Ford.";
@Override
public String getDescription() {
return DESCRIPTION;
}
}

View File

@ -0,0 +1,14 @@
package com.iluwatar.factory;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class AppTest {
@Test
void shouldExecuteWithoutExceptions() {
assertDoesNotThrow(() -> App.main(new String[]{}));
}
}

View File

@ -0,0 +1,15 @@
package com.iluwatar.factory;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class CarsFactoryTest {
@Test
void shouldReturnFerrariInstance() {
final var ferrari = CarsFactory.getCar(CarType.FERRARI);
assertTrue(ferrari instanceof Ferrari);
}
}

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -9,23 +9,25 @@ tags:
---
## Intent
A fluent interface provides an easy-readable, flowing interface, that often mimics a domain specific language. Using
this pattern results in code that can be read nearly as human language.
A fluent interface provides an easy-readable, flowing interface, that often mimics a domain specific
language. Using this pattern results in code that can be read nearly as human language.
## Explanation
The Fluent Interface pattern is useful when you want to provide an easy readable, flowing API. Those interfaces tend
to mimic domain specific languages, so they can nearly be read as human languages.
The Fluent Interface pattern is useful when you want to provide an easy readable, flowing API. Those
interfaces tend to mimic domain specific languages, so they can nearly be read as human languages.
A fluent interface can be implemented using any of
* Method Chaining - calling a method returns some object on which further methods can be called.
* Static Factory Methods and Imports
* Method chaining - calling a method returns some object on which further methods can be called.
* Static factory methods and imports.
* Named parameters - can be simulated in Java using static factory methods.
Real world example
> We need to select numbers based on different criteria from the list. It's a great chance to utilize fluent interface pattern to provide readable easy-to-use developer experience.
> We need to select numbers based on different criteria from the list. It's a great chance to
> utilize fluent interface pattern to provide readable easy-to-use developer experience.
In plain words
@ -33,7 +35,9 @@ In plain words
Wikipedia says
> In software engineering, a fluent interface is an object-oriented API whose design relies extensively on method chaining. Its goal is to increase code legibility by creating a domain-specific language (DSL).
> In software engineering, a fluent interface is an object-oriented API whose design relies
> extensively on method chaining. Its goal is to increase code legibility by creating a
> domain-specific language (DSL).
**Programmatic Example**
@ -134,29 +138,35 @@ result is printed afterwards.
.first(2)
.last()
.ifPresent(number -> LOGGER.info("Last amongst first two negatives: {}", number));
// The initial list contains: 1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, -68.
// The first three negative values are: -61, -22, -87.
// The last two positive values are: 23, 2.
// The first even number is: 14
// A string-mapped list of negative numbers contains: String[-61], String[-22], String[-87], String[-82], String[-98], String[-68].
// The lazy list contains the last two of the first four positive numbers mapped to Strings: String[18], String[6].
// Last amongst first two negatives: -22
```
Program output:
```java
The initial list contains: 1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, -68.
The first three negative values are: -61, -22, -87.
The last two positive values are: 23, 2.
The first even number is: 14
A string-mapped list of negative numbers contains: String[-61], String[-22], String[-87], String[-82], String[-98], String[-68].
The lazy list contains the last two of the first four positive numbers mapped to Strings: String[18], String[6].
Last amongst first two negatives: -22
```
## Class diagram
![Fluent Interface](./etc/fluentinterface.png "Fluent Interface")
## Applicability
Use the Fluent Interface pattern when
* You provide an API that would benefit from a DSL-like usage
* You have objects that are difficult to configure or use
* You provide an API that would benefit from a DSL-like usage.
* You have objects that are difficult to configure or use.
## Known uses
* [Java 8 Stream API](http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html)
* [Google Guava FluentInterable](https://github.com/google/guava/wiki/FunctionalExplained)
* [Google Guava FluentIterable](https://github.com/google/guava/wiki/FunctionalExplained)
* [JOOQ](http://www.jooq.org/doc/3.0/manual/getting-started/use-cases/jooq-as-a-standalone-sql-builder/)
* [Mockito](http://mockito.org/)
* [Java Hamcrest](http://code.google.com/p/hamcrest/wiki/Tutorial)

View File

@ -29,7 +29,7 @@
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -23,8 +23,6 @@
package com.iluwatar.fluentinterface.app;
import static java.lang.String.valueOf;
import com.iluwatar.fluentinterface.fluentiterable.FluentIterable;
import com.iluwatar.fluentinterface.fluentiterable.lazy.LazyFluentIterable;
import com.iluwatar.fluentinterface.fluentiterable.simple.SimpleFluentIterable;

View File

@ -70,7 +70,7 @@ public class LazyFluentIterable<E> implements FluentIterable<E> {
return new LazyFluentIterable<>() {
@Override
public Iterator<E> iterator() {
return new DecoratingIterator<E>(iterable.iterator()) {
return new DecoratingIterator<>(iterable.iterator()) {
@Override
public E computeNext() {
while (fromIterator.hasNext()) {
@ -107,10 +107,10 @@ public class LazyFluentIterable<E> implements FluentIterable<E> {
*/
@Override
public FluentIterable<E> first(int count) {
return new LazyFluentIterable<E>() {
return new LazyFluentIterable<>() {
@Override
public Iterator<E> iterator() {
return new DecoratingIterator<E>(iterable.iterator()) {
return new DecoratingIterator<>(iterable.iterator()) {
int currentIndex;
@Override
@ -149,10 +149,10 @@ public class LazyFluentIterable<E> implements FluentIterable<E> {
*/
@Override
public FluentIterable<E> last(int count) {
return new LazyFluentIterable<E>() {
return new LazyFluentIterable<>() {
@Override
public Iterator<E> iterator() {
return new DecoratingIterator<E>(iterable.iterator()) {
return new DecoratingIterator<>(iterable.iterator()) {
private int stopIndex;
private int totalElementsCount;
private List<E> list;
@ -194,10 +194,10 @@ public class LazyFluentIterable<E> implements FluentIterable<E> {
*/
@Override
public <T> FluentIterable<T> map(Function<? super E, T> function) {
return new LazyFluentIterable<T>() {
return new LazyFluentIterable<>() {
@Override
public Iterator<T> iterator() {
return new DecoratingIterator<T>(null) {
return new DecoratingIterator<>(null) {
final Iterator<E> oldTypeIterator = iterable.iterator();
@Override
@ -226,7 +226,7 @@ public class LazyFluentIterable<E> implements FluentIterable<E> {
@Override
public Iterator<E> iterator() {
return new DecoratingIterator<E>(iterable.iterator()) {
return new DecoratingIterator<>(iterable.iterator()) {
@Override
public E computeNext() {
return fromIterator.hasNext() ? fromIterator.next() : null;

View File

@ -29,7 +29,7 @@
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.23.0-SNAPSHOT</version>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>flux</artifactId>
<dependencies>

Some files were not shown because too many files have changed in this diff Show More