Compare commits
2 Commits
all-contri
...
all-contri
Author | SHA1 | Date | |
---|---|---|---|
3e77480f67 | |||
a0c75438eb |
@ -1341,51 +1341,6 @@
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "warp125",
|
||||
"name": "warp125",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/48073115?v=4",
|
||||
"profile": "https://github.com/warp125",
|
||||
"contributions": [
|
||||
"translation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "tkhadir",
|
||||
"name": "KHADIR Tayeb",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/45130488?v=4",
|
||||
"profile": "http://libkhadir.fr",
|
||||
"contributions": [
|
||||
"translation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ignite1771",
|
||||
"name": "ignite1771",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/59446563?v=4",
|
||||
"profile": "https://github.com/ignite1771",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "demirhalil",
|
||||
"name": "Halil Demir",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/22895118?v=4",
|
||||
"profile": "https://github.com/demirhalil",
|
||||
"contributions": [
|
||||
"translation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "rohit10000",
|
||||
"name": "Rohit Singh",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/20845565?v=4",
|
||||
"profile": "https://github.com/rohit10000",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 4,
|
||||
|
8
.gitignore
vendored
@ -4,8 +4,7 @@ target
|
||||
.classpath
|
||||
.project
|
||||
*.class
|
||||
|
||||
### Package Files ###
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
@ -14,8 +13,7 @@ target
|
||||
*.swp
|
||||
datanucleus.log
|
||||
/bin/
|
||||
/bin/
|
||||
/bin/
|
||||
*.log
|
||||
event-sourcing/Journal.json
|
||||
|
||||
### Checkstyle ###
|
||||
.checkstyle
|
||||
|
312
README.md
@ -10,15 +10,9 @@
|
||||
[](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
|
||||
[](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
<br/>
|
||||
|
||||
Read in different language : [**CN**](/zh/README.md),[**KR**](/ko/README.md),[**FR**](/fr/README.md),[**TR**](/tr/README.md),
|
||||
|
||||
<br/>
|
||||
|
||||
# Introduction
|
||||
|
||||
Design patterns are the best formalized practices a programmer can use to
|
||||
@ -76,236 +70,228 @@ This project is licensed under the terms of the MIT license.
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/iluwatar"><img src="https://avatars1.githubusercontent.com/u/582346?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ilkka Seppälä</b></sub></a><br /><a href="#projectManagement-iluwatar" title="Project Management">📆</a> <a href="#maintenance-iluwatar" title="Maintenance">🚧</a> <a href="#content-iluwatar" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://github.com/amit1307"><img src="https://avatars0.githubusercontent.com/u/23420222?v=4?s=100" width="100px;" alt=""/><br /><sub><b>amit1307</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=amit1307" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/npathai"><img src="https://avatars2.githubusercontent.com/u/1792515?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Narendra Pathai</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=npathai" title="Code">💻</a> <a href="#ideas-npathai" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Anpathai" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://github.com/fluxw42"><img src="https://avatars1.githubusercontent.com/u/1545460?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jeroen Meulemeester</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=fluxw42" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/iluwatar"><img src="https://avatars1.githubusercontent.com/u/582346?v=4" width="100px;" alt=""/><br /><sub><b>Ilkka Seppälä</b></sub></a><br /><a href="#projectManagement-iluwatar" title="Project Management">📆</a> <a href="#maintenance-iluwatar" title="Maintenance">🚧</a> <a href="#content-iluwatar" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://github.com/amit1307"><img src="https://avatars0.githubusercontent.com/u/23420222?v=4" width="100px;" alt=""/><br /><sub><b>amit1307</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=amit1307" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/npathai"><img src="https://avatars2.githubusercontent.com/u/1792515?v=4" width="100px;" alt=""/><br /><sub><b>Narendra Pathai</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=npathai" title="Code">💻</a> <a href="#ideas-npathai" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Anpathai" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://github.com/fluxw42"><img src="https://avatars1.githubusercontent.com/u/1545460?v=4" width="100px;" alt=""/><br /><sub><b>Jeroen Meulemeester</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=fluxw42" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://www.joemccarthy.co.uk"><img src="https://avatars0.githubusercontent.com/u/4526195?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joseph McCarthy</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=mikulucky" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/thomasoss"><img src="https://avatars1.githubusercontent.com/u/22516154?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Thomas</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=thomasoss" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/anuragagarwal561994"><img src="https://avatars1.githubusercontent.com/u/6075379?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Anurag Agarwal</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=anuragagarwal561994" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://markusmo3.github.io"><img src="https://avatars1.githubusercontent.com/u/3317416?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Markus Moser</b></sub></a><br /><a href="#design-markusmo3" title="Design">🎨</a> <a href="https://github.com/iluwatar/java-design-patterns/commits?author=markusmo3" title="Code">💻</a> <a href="#ideas-markusmo3" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="http://www.joemccarthy.co.uk"><img src="https://avatars0.githubusercontent.com/u/4526195?v=4" width="100px;" alt=""/><br /><sub><b>Joseph McCarthy</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=mikulucky" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/thomasoss"><img src="https://avatars1.githubusercontent.com/u/22516154?v=4" width="100px;" alt=""/><br /><sub><b>Thomas</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=thomasoss" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/anuragagarwal561994"><img src="https://avatars1.githubusercontent.com/u/6075379?v=4" width="100px;" alt=""/><br /><sub><b>Anurag Agarwal</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=anuragagarwal561994" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://markusmo3.github.io"><img src="https://avatars1.githubusercontent.com/u/3317416?v=4" width="100px;" alt=""/><br /><sub><b>Markus Moser</b></sub></a><br /><a href="#design-markusmo3" title="Design">🎨</a> <a href="https://github.com/iluwatar/java-design-patterns/commits?author=markusmo3" title="Code">💻</a> <a href="#ideas-markusmo3" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://twitter.com/i_sabiq"><img src="https://avatars1.githubusercontent.com/u/19510920?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sabiq Ihab</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=isabiq" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://inbravo.github.io"><img src="https://avatars3.githubusercontent.com/u/5253764?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Amit Dixit</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=inbravo" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/piyushchaudhari04"><img src="https://avatars3.githubusercontent.com/u/10268029?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Piyush Kailash Chaudhari</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=piyushchaudhari04" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/joshzambales"><img src="https://avatars1.githubusercontent.com/u/8704552?v=4?s=100" width="100px;" alt=""/><br /><sub><b>joshzambales</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=joshzambales" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://twitter.com/i_sabiq"><img src="https://avatars1.githubusercontent.com/u/19510920?v=4" width="100px;" alt=""/><br /><sub><b>Sabiq Ihab</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=isabiq" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://inbravo.github.io"><img src="https://avatars3.githubusercontent.com/u/5253764?v=4" width="100px;" alt=""/><br /><sub><b>Amit Dixit</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=inbravo" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/piyushchaudhari04"><img src="https://avatars3.githubusercontent.com/u/10268029?v=4" width="100px;" alt=""/><br /><sub><b>Piyush Kailash Chaudhari</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=piyushchaudhari04" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/joshzambales"><img src="https://avatars1.githubusercontent.com/u/8704552?v=4" width="100px;" alt=""/><br /><sub><b>joshzambales</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=joshzambales" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/Crossy147"><img src="https://avatars2.githubusercontent.com/u/7272996?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kamil Pietruszka</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Crossy147" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://cs.joensuu.fi/~zkhayda"><img src="https://avatars2.githubusercontent.com/u/660742?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zafar Khaydarov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=zafarella" title="Code">💻</a> <a href="https://github.com/iluwatar/java-design-patterns/commits?author=zafarella" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://kemitix.github.io/"><img src="https://avatars1.githubusercontent.com/u/1147749?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Paul Campbell</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=kemitix" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Argyro-Sioziou"><img src="https://avatars0.githubusercontent.com/u/22822639?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Argyro Sioziou</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Argyro-Sioziou" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Crossy147"><img src="https://avatars2.githubusercontent.com/u/7272996?v=4" width="100px;" alt=""/><br /><sub><b>Kamil Pietruszka</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Crossy147" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://cs.joensuu.fi/~zkhayda"><img src="https://avatars2.githubusercontent.com/u/660742?v=4" width="100px;" alt=""/><br /><sub><b>Zafar Khaydarov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=zafarella" title="Code">💻</a> <a href="https://github.com/iluwatar/java-design-patterns/commits?author=zafarella" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://kemitix.github.io/"><img src="https://avatars1.githubusercontent.com/u/1147749?v=4" width="100px;" alt=""/><br /><sub><b>Paul Campbell</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=kemitix" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Argyro-Sioziou"><img src="https://avatars0.githubusercontent.com/u/22822639?v=4" width="100px;" alt=""/><br /><sub><b>Argyro Sioziou</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Argyro-Sioziou" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/TylerMcConville"><img src="https://avatars0.githubusercontent.com/u/4946449?v=4?s=100" width="100px;" alt=""/><br /><sub><b>TylerMcConville</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=TylerMcConville" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/saksham93"><img src="https://avatars1.githubusercontent.com/u/37399540?v=4?s=100" width="100px;" alt=""/><br /><sub><b>saksham93</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=saksham93" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/nikhilbarar"><img src="https://avatars2.githubusercontent.com/u/37332144?v=4?s=100" width="100px;" alt=""/><br /><sub><b>nikhilbarar</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=nikhilbarar" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://colinbut.com"><img src="https://avatars2.githubusercontent.com/u/10725674?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Colin But</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=colinbut" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/TylerMcConville"><img src="https://avatars0.githubusercontent.com/u/4946449?v=4" width="100px;" alt=""/><br /><sub><b>TylerMcConville</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=TylerMcConville" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/saksham93"><img src="https://avatars1.githubusercontent.com/u/37399540?v=4" width="100px;" alt=""/><br /><sub><b>saksham93</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=saksham93" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/nikhilbarar"><img src="https://avatars2.githubusercontent.com/u/37332144?v=4" width="100px;" alt=""/><br /><sub><b>nikhilbarar</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=nikhilbarar" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://colinbut.com"><img src="https://avatars2.githubusercontent.com/u/10725674?v=4" width="100px;" alt=""/><br /><sub><b>Colin But</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=colinbut" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/ruslanpa"><img src="https://avatars2.githubusercontent.com/u/1503411?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ruslan</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ruslanpa" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/JuhoKang"><img src="https://avatars1.githubusercontent.com/u/4745294?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Juho Kang</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=JuhoKang" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/dheeraj-mummareddy"><img src="https://avatars2.githubusercontent.com/u/7002230?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dheeraj Mummareddy</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=dheeraj-mummareddy" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.bernardosulzbach.com"><img src="https://avatars0.githubusercontent.com/u/8271090?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bernardo Sulzbach</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=bernardosulzbach" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ruslanpa"><img src="https://avatars2.githubusercontent.com/u/1503411?v=4" width="100px;" alt=""/><br /><sub><b>Ruslan</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ruslanpa" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/JuhoKang"><img src="https://avatars1.githubusercontent.com/u/4745294?v=4" width="100px;" alt=""/><br /><sub><b>Juho Kang</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=JuhoKang" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/dheeraj-mummareddy"><img src="https://avatars2.githubusercontent.com/u/7002230?v=4" width="100px;" alt=""/><br /><sub><b>Dheeraj Mummareddy</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=dheeraj-mummareddy" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.bernardosulzbach.com"><img src="https://avatars0.githubusercontent.com/u/8271090?v=4" width="100px;" alt=""/><br /><sub><b>Bernardo Sulzbach</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=bernardosulzbach" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/4lexis"><img src="https://avatars0.githubusercontent.com/u/19871727?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aleksandar Dudukovic</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=4lexis" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.yusufaytas.com"><img src="https://avatars2.githubusercontent.com/u/1049483?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yusuf Aytaş</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=yusufaytas" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://futurehomes.hu"><img src="https://avatars2.githubusercontent.com/u/1001491?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mihály Kuprivecz</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=qpi" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/kapinuss"><img src="https://avatars0.githubusercontent.com/u/17639945?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stanislav Kapinus</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=kapinuss" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/4lexis"><img src="https://avatars0.githubusercontent.com/u/19871727?v=4" width="100px;" alt=""/><br /><sub><b>Aleksandar Dudukovic</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=4lexis" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.yusufaytas.com"><img src="https://avatars2.githubusercontent.com/u/1049483?v=4" width="100px;" alt=""/><br /><sub><b>Yusuf Aytaş</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=yusufaytas" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://futurehomes.hu"><img src="https://avatars2.githubusercontent.com/u/1001491?v=4" width="100px;" alt=""/><br /><sub><b>Mihály Kuprivecz</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=qpi" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/kapinuss"><img src="https://avatars0.githubusercontent.com/u/17639945?v=4" width="100px;" alt=""/><br /><sub><b>Stanislav Kapinus</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=kapinuss" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/gvsharma"><img src="https://avatars1.githubusercontent.com/u/6648152?v=4?s=100" width="100px;" alt=""/><br /><sub><b>GVSharma</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=gvsharma" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/SrdjanPaunovic"><img src="https://avatars1.githubusercontent.com/u/22815104?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Srđan Paunović</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=SrdjanPaunovic" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://sideris.xyz/"><img src="https://avatars3.githubusercontent.com/u/5484694?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Petros G. Sideris</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=sideris" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/pramodgupta3/"><img src="https://avatars1.githubusercontent.com/u/2184241?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pramod Gupta</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AIAmPramod" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://github.com/gvsharma"><img src="https://avatars1.githubusercontent.com/u/6648152?v=4" width="100px;" alt=""/><br /><sub><b>GVSharma</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=gvsharma" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/SrdjanPaunovic"><img src="https://avatars1.githubusercontent.com/u/22815104?v=4" width="100px;" alt=""/><br /><sub><b>Srđan Paunović</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=SrdjanPaunovic" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://sideris.xyz/"><img src="https://avatars3.githubusercontent.com/u/5484694?v=4" width="100px;" alt=""/><br /><sub><b>Petros G. Sideris</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=sideris" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/pramodgupta3/"><img src="https://avatars1.githubusercontent.com/u/2184241?v=4" width="100px;" alt=""/><br /><sub><b>Pramod Gupta</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AIAmPramod" title="Reviewed Pull Requests">👀</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://amarnath510.github.io/portfolio"><img src="https://avatars0.githubusercontent.com/u/4599623?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Amarnath Chandana</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Amarnath510" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Anurag870"><img src="https://avatars1.githubusercontent.com/u/6295975?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Anurag870</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Anurag870" title="Code">💻</a> <a href="https://github.com/iluwatar/java-design-patterns/commits?author=Anurag870" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://theerroris.me"><img src="https://avatars0.githubusercontent.com/u/1685953?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Wes Gilleland</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Deathnerd" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Harshrajsinh"><img src="https://avatars2.githubusercontent.com/u/22811531?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Harshraj Thakor</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Harshrajsinh" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://amarnath510.github.io/portfolio"><img src="https://avatars0.githubusercontent.com/u/4599623?v=4" width="100px;" alt=""/><br /><sub><b>Amarnath Chandana</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Amarnath510" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Anurag870"><img src="https://avatars1.githubusercontent.com/u/6295975?v=4" width="100px;" alt=""/><br /><sub><b>Anurag870</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Anurag870" title="Code">💻</a> <a href="https://github.com/iluwatar/java-design-patterns/commits?author=Anurag870" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://theerroris.me"><img src="https://avatars0.githubusercontent.com/u/1685953?v=4" width="100px;" alt=""/><br /><sub><b>Wes Gilleland</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Deathnerd" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Harshrajsinh"><img src="https://avatars2.githubusercontent.com/u/22811531?v=4" width="100px;" alt=""/><br /><sub><b>Harshraj Thakor</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Harshrajsinh" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/MaVdbussche"><img src="https://avatars1.githubusercontent.com/u/26136934?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Martin Vandenbussche</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=MaVdbussche" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://alexsomai.com"><img src="https://avatars1.githubusercontent.com/u/5720977?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alexandru Somai</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=alexsomai" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/amogozov"><img src="https://avatars3.githubusercontent.com/u/7372215?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Artur Mogozov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=amogozov" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/anthonycampbell"><img src="https://avatars3.githubusercontent.com/u/10249255?v=4?s=100" width="100px;" alt=""/><br /><sub><b>anthony</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=anthonycampbell" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/MaVdbussche"><img src="https://avatars1.githubusercontent.com/u/26136934?v=4" width="100px;" alt=""/><br /><sub><b>Martin Vandenbussche</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=MaVdbussche" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://alexsomai.com"><img src="https://avatars1.githubusercontent.com/u/5720977?v=4" width="100px;" alt=""/><br /><sub><b>Alexandru Somai</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=alexsomai" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/amogozov"><img src="https://avatars3.githubusercontent.com/u/7372215?v=4" width="100px;" alt=""/><br /><sub><b>Artur Mogozov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=amogozov" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/anthonycampbell"><img src="https://avatars3.githubusercontent.com/u/10249255?v=4" width="100px;" alt=""/><br /><sub><b>anthony</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=anthonycampbell" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://ccygnus.com/"><img src="https://avatars1.githubusercontent.com/u/9342724?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Christian Cygnus</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=christophercolumbusdog" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://about.me/dzmitryh"><img src="https://avatars2.githubusercontent.com/u/5390492?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dima Gubin</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=dzmitryh" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/jjjimenez100"><img src="https://avatars3.githubusercontent.com/u/22243493?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joshua Jimenez</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=jjjimenez100" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://about.me/kaiwinter"><img src="https://avatars0.githubusercontent.com/u/110982?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kai Winter</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=kaiwinter" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://ccygnus.com/"><img src="https://avatars1.githubusercontent.com/u/9342724?v=4" width="100px;" alt=""/><br /><sub><b>Christian Cygnus</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=christophercolumbusdog" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://about.me/dzmitryh"><img src="https://avatars2.githubusercontent.com/u/5390492?v=4" width="100px;" alt=""/><br /><sub><b>Dima Gubin</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=dzmitryh" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/jjjimenez100"><img src="https://avatars3.githubusercontent.com/u/22243493?v=4" width="100px;" alt=""/><br /><sub><b>Joshua Jimenez</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=jjjimenez100" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://about.me/kaiwinter"><img src="https://avatars0.githubusercontent.com/u/110982?v=4" width="100px;" alt=""/><br /><sub><b>Kai Winter</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=kaiwinter" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/lbroman"><img src="https://avatars1.githubusercontent.com/u/86007?v=4?s=100" width="100px;" alt=""/><br /><sub><b>lbroman</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=lbroman" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://przemeknowak.com"><img src="https://avatars1.githubusercontent.com/u/3254609?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Przemek</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=pnowy" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/prafful1"><img src="https://avatars0.githubusercontent.com/u/14350274?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Prafful Agarwal</b></sub></a><br /><a href="#content-prafful1" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://github.com/sankypanhale"><img src="https://avatars1.githubusercontent.com/u/6478783?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sanket Panhale</b></sub></a><br /><a href="#content-sankypanhale" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://github.com/lbroman"><img src="https://avatars1.githubusercontent.com/u/86007?v=4" width="100px;" alt=""/><br /><sub><b>lbroman</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=lbroman" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://przemeknowak.com"><img src="https://avatars1.githubusercontent.com/u/3254609?v=4" width="100px;" alt=""/><br /><sub><b>Przemek</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=pnowy" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/prafful1"><img src="https://avatars0.githubusercontent.com/u/14350274?v=4" width="100px;" alt=""/><br /><sub><b>Prafful Agarwal</b></sub></a><br /><a href="#content-prafful1" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://github.com/sankypanhale"><img src="https://avatars1.githubusercontent.com/u/6478783?v=4" width="100px;" alt=""/><br /><sub><b>Sanket Panhale</b></sub></a><br /><a href="#content-sankypanhale" title="Content">🖋</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/staillebois"><img src="https://avatars0.githubusercontent.com/u/23701200?v=4?s=100" width="100px;" alt=""/><br /><sub><b>staillebois</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=staillebois" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/valdar-hu"><img src="https://avatars3.githubusercontent.com/u/17962817?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Krisztián Nagy</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=valdar-hu" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.vanogrid.com"><img src="https://avatars0.githubusercontent.com/u/4307918?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alexander Ivanov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=vanogrid" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/yosfik"><img src="https://avatars3.githubusercontent.com/u/4850270?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yosfik Alqadri</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=yosfik" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/staillebois"><img src="https://avatars0.githubusercontent.com/u/23701200?v=4" width="100px;" alt=""/><br /><sub><b>staillebois</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=staillebois" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/valdar-hu"><img src="https://avatars3.githubusercontent.com/u/17962817?v=4" width="100px;" alt=""/><br /><sub><b>Krisztián Nagy</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=valdar-hu" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.vanogrid.com"><img src="https://avatars0.githubusercontent.com/u/4307918?v=4" width="100px;" alt=""/><br /><sub><b>Alexander Ivanov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=vanogrid" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/yosfik"><img src="https://avatars3.githubusercontent.com/u/4850270?v=4" width="100px;" alt=""/><br /><sub><b>Yosfik Alqadri</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=yosfik" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/7agustibm"><img src="https://avatars0.githubusercontent.com/u/8149332?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Agustí Becerra Milà</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=7agustibm" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Juaanma"><img src="https://avatars3.githubusercontent.com/u/7390500?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Juan Manuel Suárez</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Juaanma" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.devsedge.net/"><img src="https://avatars0.githubusercontent.com/u/9956006?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Luigi Cortese</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=LuigiCortese" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Rzeposlaw"><img src="https://avatars2.githubusercontent.com/u/18425745?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Katarzyna Rzepecka</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Rzeposlaw" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/7agustibm"><img src="https://avatars0.githubusercontent.com/u/8149332?v=4" width="100px;" alt=""/><br /><sub><b>Agustí Becerra Milà</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=7agustibm" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Juaanma"><img src="https://avatars3.githubusercontent.com/u/7390500?v=4" width="100px;" alt=""/><br /><sub><b>Juan Manuel Suárez</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Juaanma" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.devsedge.net/"><img src="https://avatars0.githubusercontent.com/u/9956006?v=4" width="100px;" alt=""/><br /><sub><b>Luigi Cortese</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=LuigiCortese" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Rzeposlaw"><img src="https://avatars2.githubusercontent.com/u/18425745?v=4" width="100px;" alt=""/><br /><sub><b>Katarzyna Rzepecka</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Rzeposlaw" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://adamski.pro"><img src="https://avatars1.githubusercontent.com/u/6537430?v=4?s=100" width="100px;" alt=""/><br /><sub><b>adamski.pro</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=akrystian" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/baislsl"><img src="https://avatars0.githubusercontent.com/u/17060584?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Shengli Bai</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=baislsl" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/besok"><img src="https://avatars2.githubusercontent.com/u/29834592?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Boris</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=besok" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/dmitraver"><img src="https://avatars3.githubusercontent.com/u/1798156?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dmitry Avershin</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=dmitraver" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://adamski.pro"><img src="https://avatars1.githubusercontent.com/u/6537430?v=4" width="100px;" alt=""/><br /><sub><b>adamski.pro</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=akrystian" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/baislsl"><img src="https://avatars0.githubusercontent.com/u/17060584?v=4" width="100px;" alt=""/><br /><sub><b>Shengli Bai</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=baislsl" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/besok"><img src="https://avatars2.githubusercontent.com/u/29834592?v=4" width="100px;" alt=""/><br /><sub><b>Boris</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=besok" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/dmitraver"><img src="https://avatars3.githubusercontent.com/u/1798156?v=4" width="100px;" alt=""/><br /><sub><b>Dmitry Avershin</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=dmitraver" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/fanofxiaofeng"><img src="https://avatars0.githubusercontent.com/u/3983683?v=4?s=100" width="100px;" alt=""/><br /><sub><b>靳阳</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=fanofxiaofeng" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/hoangnam2261"><img src="https://avatars2.githubusercontent.com/u/31692990?v=4?s=100" width="100px;" alt=""/><br /><sub><b>hoangnam2261</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=hoangnam2261" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/jarpit96"><img src="https://avatars2.githubusercontent.com/u/10098713?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Arpit Jain</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=jarpit96" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://joningi.net"><img src="https://avatars2.githubusercontent.com/u/6115148?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jón Ingi Sveinbjörnsson</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=joningiwork" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/fanofxiaofeng"><img src="https://avatars0.githubusercontent.com/u/3983683?v=4" width="100px;" alt=""/><br /><sub><b>靳阳</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=fanofxiaofeng" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/hoangnam2261"><img src="https://avatars2.githubusercontent.com/u/31692990?v=4" width="100px;" alt=""/><br /><sub><b>hoangnam2261</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=hoangnam2261" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/jarpit96"><img src="https://avatars2.githubusercontent.com/u/10098713?v=4" width="100px;" alt=""/><br /><sub><b>Arpit Jain</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=jarpit96" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://joningi.net"><img src="https://avatars2.githubusercontent.com/u/6115148?v=4" width="100px;" alt=""/><br /><sub><b>Jón Ingi Sveinbjörnsson</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=joningiwork" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/kirill-vlasov"><img src="https://avatars3.githubusercontent.com/u/16112495?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kirill Vlasov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=kirill-vlasov" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://mitchell-irvin.com"><img src="https://avatars0.githubusercontent.com/u/16233245?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mitchell Irvin</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=mitchellirvin" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://ranjeet-floyd.github.io"><img src="https://avatars0.githubusercontent.com/u/1992972?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ranjeet</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ranjeet-floyd" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://alwayswithme.github.io"><img src="https://avatars3.githubusercontent.com/u/3234786?v=4?s=100" width="100px;" alt=""/><br /><sub><b>PhoenixYip</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Alwayswithme" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/kirill-vlasov"><img src="https://avatars3.githubusercontent.com/u/16112495?v=4" width="100px;" alt=""/><br /><sub><b>Kirill Vlasov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=kirill-vlasov" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://mitchell-irvin.com"><img src="https://avatars0.githubusercontent.com/u/16233245?v=4" width="100px;" alt=""/><br /><sub><b>Mitchell Irvin</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=mitchellirvin" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://ranjeet-floyd.github.io"><img src="https://avatars0.githubusercontent.com/u/1992972?v=4" width="100px;" alt=""/><br /><sub><b>Ranjeet</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ranjeet-floyd" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://alwayswithme.github.io"><img src="https://avatars3.githubusercontent.com/u/3234786?v=4" width="100px;" alt=""/><br /><sub><b>PhoenixYip</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Alwayswithme" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/MSaifAsif"><img src="https://avatars1.githubusercontent.com/u/6280554?v=4?s=100" width="100px;" alt=""/><br /><sub><b>M Saif Asif</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=MSaifAsif" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/kanwarpreet25"><img src="https://avatars0.githubusercontent.com/u/39183641?v=4?s=100" width="100px;" alt=""/><br /><sub><b>kanwarpreet25</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=kanwarpreet25" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://leonmak.me"><img src="https://avatars3.githubusercontent.com/u/13071508?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Leon Mak</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=leonmak" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.wramdemark.se"><img src="https://avatars2.githubusercontent.com/u/7052193?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Per Wramdemark</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=perwramdemark" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/MSaifAsif"><img src="https://avatars1.githubusercontent.com/u/6280554?v=4" width="100px;" alt=""/><br /><sub><b>M Saif Asif</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=MSaifAsif" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/kanwarpreet25"><img src="https://avatars0.githubusercontent.com/u/39183641?v=4" width="100px;" alt=""/><br /><sub><b>kanwarpreet25</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=kanwarpreet25" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://leonmak.me"><img src="https://avatars3.githubusercontent.com/u/13071508?v=4" width="100px;" alt=""/><br /><sub><b>Leon Mak</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=leonmak" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.wramdemark.se"><img src="https://avatars2.githubusercontent.com/u/7052193?v=4" width="100px;" alt=""/><br /><sub><b>Per Wramdemark</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=perwramdemark" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/waisuan"><img src="https://avatars2.githubusercontent.com/u/10975700?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Evan Sia Wai Suan</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=waisuan" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/AnaghaSasikumar"><img src="https://avatars2.githubusercontent.com/u/42939261?v=4?s=100" width="100px;" alt=""/><br /><sub><b>AnaghaSasikumar</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=AnaghaSasikumar" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://christofferh.com"><img src="https://avatars1.githubusercontent.com/u/767643?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Christoffer Hamberg</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=christofferh" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/dgruntz"><img src="https://avatars0.githubusercontent.com/u/1516800?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dominik Gruntz</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=dgruntz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/waisuan"><img src="https://avatars2.githubusercontent.com/u/10975700?v=4" width="100px;" alt=""/><br /><sub><b>Evan Sia Wai Suan</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=waisuan" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/AnaghaSasikumar"><img src="https://avatars2.githubusercontent.com/u/42939261?v=4" width="100px;" alt=""/><br /><sub><b>AnaghaSasikumar</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=AnaghaSasikumar" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://christofferh.com"><img src="https://avatars1.githubusercontent.com/u/767643?v=4" width="100px;" alt=""/><br /><sub><b>Christoffer Hamberg</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=christofferh" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/dgruntz"><img src="https://avatars0.githubusercontent.com/u/1516800?v=4" width="100px;" alt=""/><br /><sub><b>Dominik Gruntz</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=dgruntz" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://bitbucket.org/hannespernpeintner/"><img src="https://avatars3.githubusercontent.com/u/1679437?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hannes</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=hannespernpeintner" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/leogtzr"><img src="https://avatars0.githubusercontent.com/u/1211969?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Leo Gutiérrez Ramírez</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=leogtzr" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/npczwh"><img src="https://avatars0.githubusercontent.com/u/14066422?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zhang WH</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=npczwh" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/oconnelc"><img src="https://avatars0.githubusercontent.com/u/1112973?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Christopher O'Connell</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=oconnelc" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://bitbucket.org/hannespernpeintner/"><img src="https://avatars3.githubusercontent.com/u/1679437?v=4" width="100px;" alt=""/><br /><sub><b>Hannes</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=hannespernpeintner" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/leogtzr"><img src="https://avatars0.githubusercontent.com/u/1211969?v=4" width="100px;" alt=""/><br /><sub><b>Leo Gutiérrez Ramírez</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=leogtzr" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/npczwh"><img src="https://avatars0.githubusercontent.com/u/14066422?v=4" width="100px;" alt=""/><br /><sub><b>Zhang WH</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=npczwh" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/oconnelc"><img src="https://avatars0.githubusercontent.com/u/1112973?v=4" width="100px;" alt=""/><br /><sub><b>Christopher O'Connell</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=oconnelc" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/giorgosmav21"><img src="https://avatars2.githubusercontent.com/u/22855493?v=4?s=100" width="100px;" alt=""/><br /><sub><b>George Mavroeidis</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=giorgosmav21" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/hbothra15"><img src="https://avatars1.githubusercontent.com/u/7418012?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hemant Bothra</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=hbothra15" title="Code">💻</a> <a href="#design-hbothra15" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://www.kevinpeters.net/about/"><img src="https://avatars1.githubusercontent.com/u/12736734?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Peters</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=igeligel" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://llorllale.github.io/"><img src="https://avatars1.githubusercontent.com/u/2019896?v=4?s=100" width="100px;" alt=""/><br /><sub><b>George Aristy</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=llorllale" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/giorgosmav21"><img src="https://avatars2.githubusercontent.com/u/22855493?v=4" width="100px;" alt=""/><br /><sub><b>George Mavroeidis</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=giorgosmav21" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/hbothra15"><img src="https://avatars1.githubusercontent.com/u/7418012?v=4" width="100px;" alt=""/><br /><sub><b>Hemant Bothra</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=hbothra15" title="Code">💻</a> <a href="#design-hbothra15" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://www.kevinpeters.net/about/"><img src="https://avatars1.githubusercontent.com/u/12736734?v=4" width="100px;" alt=""/><br /><sub><b>Kevin Peters</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=igeligel" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://llorllale.github.io/"><img src="https://avatars1.githubusercontent.com/u/2019896?v=4" width="100px;" alt=""/><br /><sub><b>George Aristy</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=llorllale" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/mookkiah"><img src="https://avatars1.githubusercontent.com/u/8975264?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mahendran Mookkiah</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=mookkiah" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Azureyjt"><img src="https://avatars2.githubusercontent.com/u/18476317?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Azureyjt</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Azureyjt" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/vehpsr"><img src="https://avatars2.githubusercontent.com/u/3133265?v=4?s=100" width="100px;" alt=""/><br /><sub><b>gans</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=vehpsr" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ThatGuyWithTheHat"><img src="https://avatars0.githubusercontent.com/u/24470582?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matt</b></sub></a><br /><a href="#content-ThatGuyWithTheHat" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://github.com/mookkiah"><img src="https://avatars1.githubusercontent.com/u/8975264?v=4" width="100px;" alt=""/><br /><sub><b>Mahendran Mookkiah</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=mookkiah" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Azureyjt"><img src="https://avatars2.githubusercontent.com/u/18476317?v=4" width="100px;" alt=""/><br /><sub><b>Azureyjt</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Azureyjt" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/vehpsr"><img src="https://avatars2.githubusercontent.com/u/3133265?v=4" width="100px;" alt=""/><br /><sub><b>gans</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=vehpsr" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ThatGuyWithTheHat"><img src="https://avatars0.githubusercontent.com/u/24470582?v=4" width="100px;" alt=""/><br /><sub><b>Matt</b></sub></a><br /><a href="#content-ThatGuyWithTheHat" title="Content">🖋</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/gopinathlangote/"><img src="https://avatars2.githubusercontent.com/u/10210778?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gopinath Langote</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=gopinath-langote" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/hoswey"><img src="https://avatars3.githubusercontent.com/u/3689445?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hoswey</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=hoswey" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/amit2103"><img src="https://avatars3.githubusercontent.com/u/7566692?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Amit Pandey</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=amit2103" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/gwildor28"><img src="https://avatars0.githubusercontent.com/u/16000365?v=4?s=100" width="100px;" alt=""/><br /><sub><b>gwildor28</b></sub></a><br /><a href="#content-gwildor28" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/gopinathlangote/"><img src="https://avatars2.githubusercontent.com/u/10210778?v=4" width="100px;" alt=""/><br /><sub><b>Gopinath Langote</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=gopinath-langote" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/hoswey"><img src="https://avatars3.githubusercontent.com/u/3689445?v=4" width="100px;" alt=""/><br /><sub><b>Hoswey</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=hoswey" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/amit2103"><img src="https://avatars3.githubusercontent.com/u/7566692?v=4" width="100px;" alt=""/><br /><sub><b>Amit Pandey</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=amit2103" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/gwildor28"><img src="https://avatars0.githubusercontent.com/u/16000365?v=4" width="100px;" alt=""/><br /><sub><b>gwildor28</b></sub></a><br /><a href="#content-gwildor28" title="Content">🖋</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://t.me/paul_docker"><img src="https://avatars1.githubusercontent.com/u/2404785?v=4?s=100" width="100px;" alt=""/><br /><sub><b>田浩</b></sub></a><br /><a href="#content-llitfkitfk" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://twitter.com/StPitsios"><img src="https://avatars1.githubusercontent.com/u/6773603?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stamatis Pitsios</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=pitsios-s" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/qza"><img src="https://avatars3.githubusercontent.com/u/233149?v=4?s=100" width="100px;" alt=""/><br /><sub><b>qza</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=qza" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://tschis.github.io"><img src="https://avatars1.githubusercontent.com/u/20662669?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rodolfo Forte</b></sub></a><br /><a href="#content-Tschis" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://t.me/paul_docker"><img src="https://avatars1.githubusercontent.com/u/2404785?v=4" width="100px;" alt=""/><br /><sub><b>田浩</b></sub></a><br /><a href="#content-llitfkitfk" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://twitter.com/StPitsios"><img src="https://avatars1.githubusercontent.com/u/6773603?v=4" width="100px;" alt=""/><br /><sub><b>Stamatis Pitsios</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=pitsios-s" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/qza"><img src="https://avatars3.githubusercontent.com/u/233149?v=4" width="100px;" alt=""/><br /><sub><b>qza</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=qza" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://tschis.github.io"><img src="https://avatars1.githubusercontent.com/u/20662669?v=4" width="100px;" alt=""/><br /><sub><b>Rodolfo Forte</b></sub></a><br /><a href="#content-Tschis" title="Content">🖋</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/ankurkaushal"><img src="https://avatars2.githubusercontent.com/u/2236616?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ankur Kaushal</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ankurkaushal" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/ovidijus-okinskas/"><img src="https://avatars0.githubusercontent.com/u/20372387?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ovidijus Okinskas</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=okinskas" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/robertt240"><img src="https://avatars1.githubusercontent.com/u/9137432?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robert Kasperczyk</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=robertt240" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/trautonen"><img src="https://avatars3.githubusercontent.com/u/1641063?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tapio Rautonen</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=trautonen" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ankurkaushal"><img src="https://avatars2.githubusercontent.com/u/2236616?v=4" width="100px;" alt=""/><br /><sub><b>Ankur Kaushal</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ankurkaushal" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/ovidijus-okinskas/"><img src="https://avatars0.githubusercontent.com/u/20372387?v=4" width="100px;" alt=""/><br /><sub><b>Ovidijus Okinskas</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=okinskas" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/robertt240"><img src="https://avatars1.githubusercontent.com/u/9137432?v=4" width="100px;" alt=""/><br /><sub><b>Robert Kasperczyk</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=robertt240" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/trautonen"><img src="https://avatars3.githubusercontent.com/u/1641063?v=4" width="100px;" alt=""/><br /><sub><b>Tapio Rautonen</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=trautonen" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://vk.com/yuri.orlov"><img src="https://avatars0.githubusercontent.com/u/1595733?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yuri Orlov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=yorlov" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/varunu28/"><img src="https://avatars0.githubusercontent.com/u/7676016?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Varun Upadhyay</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=varunu28" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/PalAditya"><img src="https://avatars2.githubusercontent.com/u/25523604?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aditya Pal</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=PalAditya" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/grzesiekkedzior"><img src="https://avatars3.githubusercontent.com/u/23739158?v=4?s=100" width="100px;" alt=""/><br /><sub><b>grzesiekkedzior</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=grzesiekkedzior" title="Code">💻</a> <a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Agrzesiekkedzior" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="http://vk.com/yuri.orlov"><img src="https://avatars0.githubusercontent.com/u/1595733?v=4" width="100px;" alt=""/><br /><sub><b>Yuri Orlov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=yorlov" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/varunu28/"><img src="https://avatars0.githubusercontent.com/u/7676016?v=4" width="100px;" alt=""/><br /><sub><b>Varun Upadhyay</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=varunu28" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/PalAditya"><img src="https://avatars2.githubusercontent.com/u/25523604?v=4" width="100px;" alt=""/><br /><sub><b>Aditya Pal</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=PalAditya" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/grzesiekkedzior"><img src="https://avatars3.githubusercontent.com/u/23739158?v=4" width="100px;" alt=""/><br /><sub><b>grzesiekkedzior</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=grzesiekkedzior" title="Code">💻</a> <a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Agrzesiekkedzior" title="Reviewed Pull Requests">👀</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/sivasubramanim"><img src="https://avatars2.githubusercontent.com/u/51107434?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sivasubramani M</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=sivasubramanim" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/d4gg4d"><img src="https://avatars2.githubusercontent.com/u/99457?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sami Airaksinen</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=d4gg4d" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/vertti"><img src="https://avatars0.githubusercontent.com/u/557751?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Janne Sinivirta</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=vertti" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Bobo1239"><img src="https://avatars1.githubusercontent.com/u/2302947?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Boris-Chengbiao Zhou</b></sub></a><br /><a href="#content-Bobo1239" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://github.com/sivasubramanim"><img src="https://avatars2.githubusercontent.com/u/51107434?v=4" width="100px;" alt=""/><br /><sub><b>Sivasubramani M</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=sivasubramanim" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/d4gg4d"><img src="https://avatars2.githubusercontent.com/u/99457?v=4" width="100px;" alt=""/><br /><sub><b>Sami Airaksinen</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=d4gg4d" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/vertti"><img src="https://avatars0.githubusercontent.com/u/557751?v=4" width="100px;" alt=""/><br /><sub><b>Janne Sinivirta</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=vertti" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Bobo1239"><img src="https://avatars1.githubusercontent.com/u/2302947?v=4" width="100px;" alt=""/><br /><sub><b>Boris-Chengbiao Zhou</b></sub></a><br /><a href="#content-Bobo1239" title="Content">🖋</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://jahhein.github.io"><img src="https://avatars2.githubusercontent.com/u/10779515?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jacob Hein</b></sub></a><br /><a href="#content-Jahhein" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://github.com/iamrichardjones"><img src="https://avatars3.githubusercontent.com/u/14842151?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Richard Jones</b></sub></a><br /><a href="#content-iamrichardjones" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://rachelcarmena.github.io"><img src="https://avatars0.githubusercontent.com/u/22792183?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rachel M. Carmena</b></sub></a><br /><a href="#content-rachelcarmena" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://zd-zero.github.io"><img src="https://avatars0.githubusercontent.com/u/21978370?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zaerald Denze Lungos</b></sub></a><br /><a href="#content-zd-zero" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://jahhein.github.io"><img src="https://avatars2.githubusercontent.com/u/10779515?v=4" width="100px;" alt=""/><br /><sub><b>Jacob Hein</b></sub></a><br /><a href="#content-Jahhein" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://github.com/iamrichardjones"><img src="https://avatars3.githubusercontent.com/u/14842151?v=4" width="100px;" alt=""/><br /><sub><b>Richard Jones</b></sub></a><br /><a href="#content-iamrichardjones" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://rachelcarmena.github.io"><img src="https://avatars0.githubusercontent.com/u/22792183?v=4" width="100px;" alt=""/><br /><sub><b>Rachel M. Carmena</b></sub></a><br /><a href="#content-rachelcarmena" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://zd-zero.github.io"><img src="https://avatars0.githubusercontent.com/u/21978370?v=4" width="100px;" alt=""/><br /><sub><b>Zaerald Denze Lungos</b></sub></a><br /><a href="#content-zd-zero" title="Content">🖋</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://webpro.nl"><img src="https://avatars1.githubusercontent.com/u/456426?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lars Kappert</b></sub></a><br /><a href="#content-webpro" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://xiaod.info"><img src="https://avatars2.githubusercontent.com/u/21277644?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mike Liu</b></sub></a><br /><a href="#translation-xiaod-dev" title="Translation">🌍</a></td>
|
||||
<td align="center"><a href="https://github.com/charlesfinley"><img src="https://avatars1.githubusercontent.com/u/6307904?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matt Dolan</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=charlesfinley" title="Code">💻</a> <a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Acharlesfinley" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://github.com/MananS77"><img src="https://avatars3.githubusercontent.com/u/21033516?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Manan</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AMananS77" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://webpro.nl"><img src="https://avatars1.githubusercontent.com/u/456426?v=4" width="100px;" alt=""/><br /><sub><b>Lars Kappert</b></sub></a><br /><a href="#content-webpro" title="Content">🖋</a></td>
|
||||
<td align="center"><a href="https://xiaod.info"><img src="https://avatars2.githubusercontent.com/u/21277644?v=4" width="100px;" alt=""/><br /><sub><b>Mike Liu</b></sub></a><br /><a href="#translation-xiaod-dev" title="Translation">🌍</a></td>
|
||||
<td align="center"><a href="https://github.com/charlesfinley"><img src="https://avatars1.githubusercontent.com/u/6307904?v=4" width="100px;" alt=""/><br /><sub><b>Matt Dolan</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=charlesfinley" title="Code">💻</a> <a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Acharlesfinley" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://github.com/MananS77"><img src="https://avatars3.githubusercontent.com/u/21033516?v=4" width="100px;" alt=""/><br /><sub><b>Manan</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AMananS77" title="Reviewed Pull Requests">👀</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/nishant"><img src="https://avatars2.githubusercontent.com/u/15331971?v=4?s=100" 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?s=100" 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?s=100" 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?s=100" 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>
|
||||
<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> <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>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/ashish-trivedi-218379135/"><img src="https://avatars3.githubusercontent.com/u/23194128?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ashish Trivedi</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ashishtrivedi16" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://rayyounghong.com"><img src="https://avatars1.githubusercontent.com/u/41055099?v=4?s=100" width="100px;" alt=""/><br /><sub><b>洪月阳</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=RayYH" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://xdvrx1.github.io/"><img src="https://avatars0.githubusercontent.com/u/47092464?v=4?s=100" width="100px;" alt=""/><br /><sub><b>xdvrx1</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Axdvrx1" title="Reviewed Pull Requests">👀</a> <a href="#ideas-xdvrx1" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="http://subho.xyz"><img src="https://avatars0.githubusercontent.com/u/13291222?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Subhrodip Mohanta</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ohbus" title="Code">💻</a> <a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Aohbus" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/ashish-trivedi-218379135/"><img src="https://avatars3.githubusercontent.com/u/23194128?v=4" width="100px;" alt=""/><br /><sub><b>Ashish Trivedi</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ashishtrivedi16" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://rayyounghong.com"><img src="https://avatars1.githubusercontent.com/u/41055099?v=4" width="100px;" alt=""/><br /><sub><b>洪月阳</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=RayYH" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://xdvrx1.github.io/"><img src="https://avatars0.githubusercontent.com/u/47092464?v=4" width="100px;" alt=""/><br /><sub><b>xdvrx1</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Axdvrx1" title="Reviewed Pull Requests">👀</a> <a href="#ideas-xdvrx1" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="http://subho.xyz"><img src="https://avatars0.githubusercontent.com/u/13291222?v=4" width="100px;" alt=""/><br /><sub><b>Subhrodip Mohanta</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ohbus" title="Code">💻</a> <a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Aohbus" title="Reviewed Pull Requests">👀</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/nahteb"><img src="https://avatars3.githubusercontent.com/u/13121570?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bethan Palmer</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=nahteb" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ToxicDreamz"><img src="https://avatars0.githubusercontent.com/u/45225562?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Toxic Dreamz</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ToxicDreamz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.edycutjong.com"><img src="https://avatars1.githubusercontent.com/u/1098102?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Edy Cu Tjong</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=edycutjong" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/mkrzywanski"><img src="https://avatars0.githubusercontent.com/u/15279585?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michał Krzywański</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=mkrzywanski" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/nahteb"><img src="https://avatars3.githubusercontent.com/u/13121570?v=4" width="100px;" alt=""/><br /><sub><b>Bethan Palmer</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=nahteb" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ToxicDreamz"><img src="https://avatars0.githubusercontent.com/u/45225562?v=4" width="100px;" alt=""/><br /><sub><b>Toxic Dreamz</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ToxicDreamz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.edycutjong.com"><img src="https://avatars1.githubusercontent.com/u/1098102?v=4" width="100px;" alt=""/><br /><sub><b>Edy Cu Tjong</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=edycutjong" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/mkrzywanski"><img src="https://avatars0.githubusercontent.com/u/15279585?v=4" width="100px;" alt=""/><br /><sub><b>Michał Krzywański</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=mkrzywanski" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.stefan-birkner.de"><img src="https://avatars1.githubusercontent.com/u/711349?v=4?s=100" 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?s=100" 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?s=100" 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?s=100" 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>
|
||||
<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?s=100" width="100px;" alt=""/><br /><sub><b>Swaraj</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=swarajsaaj" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://christophflick.de"><img src="https://avatars0.githubusercontent.com/u/4465376?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Christoph Flick</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ChFlick" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Ascenio"><img src="https://avatars1.githubusercontent.com/u/7662016?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ascênio</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AAscenio" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/domenico-sibilio/"><img src="https://avatars2.githubusercontent.com/u/24280982?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Domenico Sibilio</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=dsibilio" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/swarajsaaj"><img src="https://avatars2.githubusercontent.com/u/6285049?v=4" width="100px;" alt=""/><br /><sub><b>Swaraj</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=swarajsaaj" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://christophflick.de"><img src="https://avatars0.githubusercontent.com/u/4465376?v=4" width="100px;" alt=""/><br /><sub><b>Christoph Flick</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ChFlick" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Ascenio"><img src="https://avatars1.githubusercontent.com/u/7662016?v=4" width="100px;" alt=""/><br /><sub><b>Ascênio</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AAscenio" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/domenico-sibilio/"><img src="https://avatars2.githubusercontent.com/u/24280982?v=4" width="100px;" alt=""/><br /><sub><b>Domenico Sibilio</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=dsibilio" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/akashchandwani"><img src="https://avatars2.githubusercontent.com/u/3483277?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Akash Chandwani</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Aakashchandwani" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="http://www.linkedin.com/in/manannikov"><img src="https://avatars2.githubusercontent.com/u/7019769?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pavlo Manannikov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=manannikov" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/eimanip"><img src="https://avatars0.githubusercontent.com/u/20307301?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Eiman</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=eimanip" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/OrangePants-R"><img src="https://avatars0.githubusercontent.com/u/42976136?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rocky</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=OrangePants-R" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/akashchandwani"><img src="https://avatars2.githubusercontent.com/u/3483277?v=4" width="100px;" alt=""/><br /><sub><b>Akash Chandwani</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Aakashchandwani" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="http://www.linkedin.com/in/manannikov"><img src="https://avatars2.githubusercontent.com/u/7019769?v=4" width="100px;" alt=""/><br /><sub><b>Pavlo Manannikov</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=manannikov" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/eimanip"><img src="https://avatars0.githubusercontent.com/u/20307301?v=4" width="100px;" alt=""/><br /><sub><b>Eiman</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=eimanip" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/OrangePants-R"><img src="https://avatars0.githubusercontent.com/u/42976136?v=4" width="100px;" alt=""/><br /><sub><b>Rocky</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=OrangePants-R" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://ibrahimalii.github.io/"><img src="https://avatars2.githubusercontent.com/u/21141301?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ibrahim ali abdelghany</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AibrahimAlii" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://github.com/gkulkarni2020"><img src="https://avatars3.githubusercontent.com/u/5161548?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Girish Kulkarni</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=gkulkarni2020" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/omk13"><img src="https://avatars0.githubusercontent.com/u/59054172?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Omar Karazoun</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=omk13" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/jeff303"><img src="https://avatars0.githubusercontent.com/u/3521562?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jeff Evans</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=jeff303" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://ibrahimalii.github.io/"><img src="https://avatars2.githubusercontent.com/u/21141301?v=4" width="100px;" alt=""/><br /><sub><b>Ibrahim ali abdelghany</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AibrahimAlii" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://github.com/gkulkarni2020"><img src="https://avatars3.githubusercontent.com/u/5161548?v=4" width="100px;" alt=""/><br /><sub><b>Girish Kulkarni</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=gkulkarni2020" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/omk13"><img src="https://avatars0.githubusercontent.com/u/59054172?v=4" width="100px;" alt=""/><br /><sub><b>Omar Karazoun</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=omk13" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/jeff303"><img src="https://avatars0.githubusercontent.com/u/3521562?v=4" width="100px;" alt=""/><br /><sub><b>Jeff Evans</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=jeff303" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://viveksb007.github.io"><img src="https://avatars1.githubusercontent.com/u/12713808?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vivek Singh</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=viveksb007" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/siavashsoleymani"><img src="https://avatars2.githubusercontent.com/u/18074419?v=4?s=100" width="100px;" alt=""/><br /><sub><b>siavash</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=siavashsoleymani" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ruchpeanuts"><img src="https://avatars0.githubusercontent.com/u/29301900?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ruchpeanuts</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ruchpeanuts" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/warp125"><img src="https://avatars1.githubusercontent.com/u/48073115?v=4?s=100" width="100px;" alt=""/><br /><sub><b>warp125</b></sub></a><br /><a href="#translation-warp125" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://libkhadir.fr"><img src="https://avatars1.githubusercontent.com/u/45130488?v=4?s=100" width="100px;" alt=""/><br /><sub><b>KHADIR Tayeb</b></sub></a><br /><a href="#translation-tkhadir" title="Translation">🌍</a></td>
|
||||
<td align="center"><a href="https://github.com/ignite1771"><img src="https://avatars2.githubusercontent.com/u/59446563?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ignite1771</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ignite1771" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/demirhalil"><img src="https://avatars1.githubusercontent.com/u/22895118?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Halil Demir</b></sub></a><br /><a href="#translation-demirhalil" title="Translation">🌍</a></td>
|
||||
<td align="center"><a href="https://github.com/rohit10000"><img src="https://avatars.githubusercontent.com/u/20845565?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rohit Singh</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=rohit10000" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://viveksb007.github.io"><img src="https://avatars1.githubusercontent.com/u/12713808?v=4" width="100px;" alt=""/><br /><sub><b>Vivek Singh</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=viveksb007" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/siavashsoleymani"><img src="https://avatars2.githubusercontent.com/u/18074419?v=4" width="100px;" alt=""/><br /><sub><b>siavash</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=siavashsoleymani" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ruchpeanuts"><img src="https://avatars0.githubusercontent.com/u/29301900?v=4" width="100px;" alt=""/><br /><sub><b>ruchpeanuts</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ruchpeanuts" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- markdownlint-enable -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
Before Width: | Height: | Size: 310 B |
Before Width: | Height: | Size: 100 B |
Before Width: | Height: | Size: 413 B |
Before Width: | Height: | Size: 802 B |
54
data-transfer-object-enum-impl/README.md
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Data Transfer Object
|
||||
folder: data-transfer-object
|
||||
permalink: /patterns/data-transfer-object/
|
||||
categories: Architectural
|
||||
tags:
|
||||
- Performance
|
||||
---
|
||||
|
||||
## Intent
|
||||
|
||||
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.
|
||||
|
||||
In plain words
|
||||
|
||||
> Using DTO relevant information can be fetched with a single backend query.
|
||||
|
||||
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.
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
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.
|
||||
* You want reduced number of remote calls.
|
||||
|
||||
## Credits
|
||||
|
||||
* [Design Pattern - Transfer Object Pattern](https://www.tutorialspoint.com/design_pattern/transfer_object_pattern.htm)
|
||||
* [Data Transfer Object](https://msdn.microsoft.com/en-us/library/ff649585.aspx)
|
||||
* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)
|
||||
* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321127420&linkCode=as2&tag=javadesignpat-20&linkId=014237a67c9d46f384b35e10151956bd)
|
@ -0,0 +1,129 @@
|
||||
@startuml
|
||||
package com.iluwatar.datatransferenum {
|
||||
class App {
|
||||
- LOGGER : Logger {static}
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class Product {
|
||||
- cost : Double
|
||||
- id : Long
|
||||
- name : String
|
||||
- price : Double
|
||||
- supplier : String
|
||||
+ Product()
|
||||
+ getCost() : Double
|
||||
+ getId() : Long
|
||||
+ getName() : String
|
||||
+ getPrice() : Double
|
||||
+ getSupplier() : String
|
||||
+ setCost(cost : Double) : Product
|
||||
+ setId(id : Long) : Product
|
||||
+ setName(name : String) : Product
|
||||
+ setPrice(price : Double) : Product
|
||||
+ setSupplier(supplier : String) : Product
|
||||
+ toString() : String
|
||||
}
|
||||
enum ProductDTO {
|
||||
+ valueOf(name : String) : ProductDTO {static}
|
||||
+ values() : ProductDTO[] {static}
|
||||
}
|
||||
-interface Cost {
|
||||
+ getCost() : Double {abstract}
|
||||
}
|
||||
-interface Id {
|
||||
+ getId() : Long {abstract}
|
||||
}
|
||||
-interface Name {
|
||||
+ getName() : String {abstract}
|
||||
}
|
||||
-interface Price {
|
||||
+ getPrice() : Double {abstract}
|
||||
}
|
||||
enum Request {
|
||||
+ valueOf(name : String) : Request {static}
|
||||
+ values() : Request[] {static}
|
||||
}
|
||||
class Create {
|
||||
- cost : Double
|
||||
- name : String
|
||||
- price : Double
|
||||
- supplier : String
|
||||
+ Create()
|
||||
+ getCost() : Double
|
||||
+ getName() : String
|
||||
+ getPrice() : Double
|
||||
+ getSupplier() : String
|
||||
+ setCost(cost : Double) : Create
|
||||
+ setName(name : String) : Create
|
||||
+ setPrice(price : Double) : Create
|
||||
+ setSupplier(supplier : String) : Create
|
||||
}
|
||||
enum Response {
|
||||
+ valueOf(name : String) : Response {static}
|
||||
+ values() : Response[] {static}
|
||||
}
|
||||
class Private {
|
||||
- cost : Double
|
||||
- id : Long
|
||||
- name : String
|
||||
- price : Double
|
||||
+ Private()
|
||||
+ getCost() : Double
|
||||
+ getId() : Long
|
||||
+ getName() : String
|
||||
+ getPrice() : Double
|
||||
+ setCost(cost : Double) : Private
|
||||
+ setId(id : Long) : Private
|
||||
+ setName(name : String) : Private
|
||||
+ setPrice(price : Double) : Private
|
||||
+ toString() : String
|
||||
}
|
||||
class Public {
|
||||
- id : Long
|
||||
- name : String
|
||||
- price : Double
|
||||
+ Public()
|
||||
+ getId() : Long
|
||||
+ getName() : String
|
||||
+ getPrice() : Double
|
||||
+ setId(id : Long) : Public
|
||||
+ setName(name : String) : Public
|
||||
+ setPrice(price : Double) : Public
|
||||
+ toString() : String
|
||||
}
|
||||
-interface Supplier {
|
||||
+ getSupplier() : String {abstract}
|
||||
}
|
||||
class ProductResource {
|
||||
- products : List<Product>
|
||||
+ ProductResource(products : List<Product>)
|
||||
+ getAllProductsForAdmin() : List<Private>
|
||||
+ getAllProductsForCustomer() : List<Public>
|
||||
+ getProducts() : List<Product>
|
||||
+ save(createProductDTO : Create)
|
||||
}
|
||||
}
|
||||
Create ..+ Request
|
||||
Request ..+ ProductDTO
|
||||
Private ..+ Response
|
||||
Supplier ..+ ProductDTO
|
||||
Name ..+ ProductDTO
|
||||
ProductResource --> "-products" Product
|
||||
Public ..+ Response
|
||||
Id ..+ ProductDTO
|
||||
Price ..+ ProductDTO
|
||||
Response ..+ ProductDTO
|
||||
Cost ..+ ProductDTO
|
||||
Create ..|> Name
|
||||
Create ..|> Price
|
||||
Create ..|> Cost
|
||||
Create ..|> Supplier
|
||||
Private ..|> Id
|
||||
Private ..|> Name
|
||||
Private ..|> Price
|
||||
Private ..|> Cost
|
||||
Public ..|> Id
|
||||
Public ..|> Name
|
||||
Public ..|> Price
|
||||
@enduml
|
BIN
data-transfer-object-enum-impl/etc/dto-enum-uml.png
Normal file
After Width: | Height: | Size: 120 KiB |
@ -23,17 +23,15 @@
|
||||
THE SOFTWARE.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.24.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>special-case</artifactId>
|
||||
<artifactId>data-transfer-object-enum-impl</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
@ -41,6 +39,23 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.iluwatar.datatransferenum.App</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,59 @@
|
||||
package com.iluwatar.datatransferenum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The Data Transfer Object pattern is a design pattern in which an data transfer object is used to
|
||||
* serve related information together to avoid multiple call for each piece of information.
|
||||
*
|
||||
* <p>In this example, ({@link App}) as as product details consumer i.e. client to
|
||||
* request for product details to server.
|
||||
*
|
||||
* <p>productResource ({@link ProductResource}) act as server to serve product information. And
|
||||
* The productDto ({@link ProductDto} is data transfer object to share product information.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
||||
|
||||
/**
|
||||
* Method as act client and request to server for details.
|
||||
*
|
||||
* @param args program argument.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Product tv =
|
||||
new Product().setId(1L).setName("TV").setSupplier("Sony").setPrice(1000D).setCost(1090D);
|
||||
Product microwave =
|
||||
new Product().setId(2L).setName("microwave").setSupplier("Delonghi").setPrice(1000D)
|
||||
.setCost(1090D);
|
||||
Product refrigerator =
|
||||
new Product().setId(3L).setName("refrigerator").setSupplier("Botsch").setPrice(1000D)
|
||||
.setCost(1090D);
|
||||
Product airConditioner =
|
||||
new Product().setId(4L).setName("airConditioner").setSupplier("LG").setPrice(1000D)
|
||||
.setCost(1090D);
|
||||
List<Product> products =
|
||||
new ArrayList<>(Arrays.asList(tv, microwave, refrigerator, airConditioner));
|
||||
ProductResource productResource = new ProductResource(products);
|
||||
|
||||
LOGGER.info("####### List of products including sensitive data just for admins: \n {}",
|
||||
Arrays.toString(productResource.getAllProductsForAdmin().toArray()));
|
||||
LOGGER.info("####### List of products for customers: \n {}",
|
||||
Arrays.toString(productResource.getAllProductsForCustomer().toArray()));
|
||||
|
||||
LOGGER.info("####### Going to save Sony PS5 ...");
|
||||
ProductDto.Request.Create createProductRequestDto = new ProductDto.Request.Create()
|
||||
.setName("PS5")
|
||||
.setCost(1000D)
|
||||
.setPrice(1220D)
|
||||
.setSupplier("Sony");
|
||||
productResource.save(createProductRequestDto);
|
||||
LOGGER.info("####### List of products after adding PS5: {}",
|
||||
Arrays.toString(productResource.getProducts().toArray()));
|
||||
}
|
||||
}
|
@ -1,27 +1,4 @@
|
||||
/*
|
||||
* 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.datatransfer.product;
|
||||
package com.iluwatar.datatransferenum;
|
||||
|
||||
/**
|
||||
* {@link Product} is a entity class for product entity. This class act as entity in the demo.
|
@ -1,27 +1,4 @@
|
||||
/*
|
||||
* 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.datatransfer.product;
|
||||
package com.iluwatar.datatransferenum;
|
||||
|
||||
/**
|
||||
* {@link ProductDto} is a data transfer object POJO.
|
@ -1,27 +1,4 @@
|
||||
/*
|
||||
* 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.datatransfer.product;
|
||||
package com.iluwatar.datatransferenum;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
@ -21,27 +21,24 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
package com.iluwatar.datatransferenum;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
public class ReceiptDto implements ReceiptViewModel {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ReceiptDto.class);
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
private Double price;
|
||||
class AppTest {
|
||||
|
||||
public ReceiptDto(Double price) {
|
||||
this.price = price;
|
||||
}
|
||||
/**
|
||||
* Issue: Add at least one assertion to this test case.
|
||||
* <p>
|
||||
* Solution: Inserted assertion to check whether the execution of the main method in {@link App#main(String[])}
|
||||
* throws an exception.
|
||||
*/
|
||||
|
||||
public Double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
LOGGER.info("Receipt: " + price + " paid");
|
||||
@Test
|
||||
void shouldExecuteApplicationWithoutException() {
|
||||
assertDoesNotThrow(() -> App.main(new String[] {}));
|
||||
}
|
||||
}
|
@ -23,13 +23,7 @@
|
||||
|
||||
package com.iluwatar.datatransfer;
|
||||
|
||||
import com.iluwatar.datatransfer.customer.CustomerDto;
|
||||
import com.iluwatar.datatransfer.customer.CustomerResource;
|
||||
import com.iluwatar.datatransfer.product.Product;
|
||||
import com.iluwatar.datatransfer.product.ProductDto;
|
||||
import com.iluwatar.datatransfer.product.ProductResource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -38,17 +32,11 @@ import org.slf4j.LoggerFactory;
|
||||
* The Data Transfer Object pattern is a design pattern in which an data transfer object is used to
|
||||
* serve related information together to avoid multiple call for each piece of information.
|
||||
*
|
||||
* <p>In the first example, {@link App} is a customer details consumer i.e. client to
|
||||
* request for customer details to server. {@link CustomerResource} act as server to serve customer
|
||||
* information. {@link CustomerDto} is data transfer object to share customer information.
|
||||
*
|
||||
* <p>In the second example, {@link App} is a product details consumer i.e. client to
|
||||
* request for product details to server. {@link ProductResource} acts as server to serve
|
||||
* product information. {@link ProductDto} is data transfer object to share product information.
|
||||
*
|
||||
* <p>The pattern implementation is a bit different in each of the examples. The first can be
|
||||
* thought as a traditional example and the second is an enum based implementation.
|
||||
* <p>In this example, ({@link App}) as as customer details consumer i.e. client to
|
||||
* request for customer details to server.
|
||||
*
|
||||
* <p>CustomerResource ({@link CustomerResource}) act as server to serve customer information. And
|
||||
* The CustomerDto ({@link CustomerDto} is data transfer object to share customer information.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
@ -60,8 +48,6 @@ public class App {
|
||||
* @param args program argument.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
// Example 1: Customer DTO
|
||||
var customerOne = new CustomerDto("1", "Kelly", "Brown");
|
||||
var customerTwo = new CustomerDto("2", "Alfonso", "Bass");
|
||||
var customers = new ArrayList<>(List.of(customerOne, customerTwo));
|
||||
@ -86,53 +72,6 @@ public class App {
|
||||
customerResource.save(customerThree);
|
||||
allCustomers = customerResource.getAllCustomers();
|
||||
printCustomerDetails(allCustomers);
|
||||
|
||||
// Example 2: Product DTO
|
||||
Product tv =
|
||||
new Product().setId(1L).setName("TV").setSupplier("Sony").setPrice(1000D).setCost(1090D);
|
||||
Product microwave =
|
||||
new Product()
|
||||
.setId(2L)
|
||||
.setName("microwave")
|
||||
.setSupplier("Delonghi")
|
||||
.setPrice(1000D)
|
||||
.setCost(1090D);
|
||||
Product refrigerator =
|
||||
new Product()
|
||||
.setId(3L)
|
||||
.setName("refrigerator")
|
||||
.setSupplier("Botsch")
|
||||
.setPrice(1000D)
|
||||
.setCost(1090D);
|
||||
Product airConditioner =
|
||||
new Product()
|
||||
.setId(4L)
|
||||
.setName("airConditioner")
|
||||
.setSupplier("LG")
|
||||
.setPrice(1000D)
|
||||
.setCost(1090D);
|
||||
List<Product> products =
|
||||
new ArrayList<>(Arrays.asList(tv, microwave, refrigerator, airConditioner));
|
||||
ProductResource productResource = new ProductResource(products);
|
||||
|
||||
LOGGER.info(
|
||||
"####### List of products including sensitive data just for admins: \n {}",
|
||||
Arrays.toString(productResource.getAllProductsForAdmin().toArray()));
|
||||
LOGGER.info(
|
||||
"####### List of products for customers: \n {}",
|
||||
Arrays.toString(productResource.getAllProductsForCustomer().toArray()));
|
||||
|
||||
LOGGER.info("####### Going to save Sony PS5 ...");
|
||||
ProductDto.Request.Create createProductRequestDto =
|
||||
new ProductDto.Request.Create()
|
||||
.setName("PS5")
|
||||
.setCost(1000D)
|
||||
.setPrice(1220D)
|
||||
.setSupplier("Sony");
|
||||
productResource.save(createProductRequestDto);
|
||||
LOGGER.info(
|
||||
"####### List of products after adding PS5: {}",
|
||||
Arrays.toString(productResource.getProducts().toArray()));
|
||||
}
|
||||
|
||||
private static void printCustomerDetails(List<CustomerDto> allCustomers) {
|
||||
|
@ -21,7 +21,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.datatransfer.customer;
|
||||
package com.iluwatar.datatransfer;
|
||||
|
||||
/**
|
||||
* {@link CustomerDto} is a data transfer object POJO. Instead of sending individual information to
|
@ -21,7 +21,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.datatransfer.customer;
|
||||
package com.iluwatar.datatransfer;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -21,16 +21,13 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.datatransfer.customer;
|
||||
package com.iluwatar.datatransfer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.iluwatar.datatransfer.customer.CustomerDto;
|
||||
import com.iluwatar.datatransfer.customer.CustomerResource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
60
fr/README.md
@ -1,60 +0,0 @@
|
||||
<!-- Cette ligne doit restée vide pour des raisons de formatage
|
||||
afin qu'on puisse avoir un affichage agréable comme sur un
|
||||
site web par exemple -->
|
||||
|
||||
# Les patrons de conception implémentés en Java
|
||||
|
||||

|
||||
[](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)
|
||||
[](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
|
||||
[](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
|
||||
[](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
# Introduction
|
||||
|
||||
Le patron de conception est la meilleure formatalisation qu'un programmeur
|
||||
peut utiliser pour résoudre un problème lors d'une conception d'une application/system.
|
||||
|
||||
Le patron de conception (design pattern) est là pour accélérer le processus de
|
||||
développement en fournissant des paradigmes éprouvés.
|
||||
|
||||
La réutilisation de patron de conception aide à prévenir des problèmes subtiles mais
|
||||
qui sont à l'origine de problèmes majeures, comme cette pratique augmente la lisibilitée
|
||||
du code par les développeurs/architectes familiers avec l'utilisation de ces concepts.
|
||||
|
||||
# Commencer
|
||||
|
||||
Ce site présente des modèles de conception Java. Les solutions ont été développées par des
|
||||
développeurs et architectes expérimentés de la communauté open source. Les modèles peuvent être parcourus par leurs descriptions de haut niveau ou en regardant leur code source. Les exemples de code source sont bien commentés et peuvent être considérés comme tutoriels de programmation sur la façon d'implémenter un modèle spécifique. Nous utilisons le plus technologies Java open source éprouvées au combat.
|
||||
|
||||
Avant de plonger dans le matériau, vous devez vous familiariser avec divers
|
||||
[Principes de conception de logiciels](https://java-design-patterns.com/principles/).
|
||||
|
||||
Toutes les conceptions doivent être aussi simples que possible. Vous devriez commencer par KISS, YAGNI,
|
||||
et faire la chose la plus simple qui pourrait éventuellement fonctionner principes. Complexité et
|
||||
les modèles ne devraient être introduits que lorsqu'ils sont nécessaires pour
|
||||
extensibilité.
|
||||
|
||||
Une fois que vous êtes familiarisé avec ces concepts, vous pouvez commencer à explorer
|
||||
[modèles de conception disponibles](https://java-design-patterns.com/patterns/) par tout
|
||||
des approches suivantes
|
||||
|
||||
- Recherchez un modèle spécifique par son nom. Vous n'en trouvez pas? Veuillez signaler un nouveau modèle [ici](https://github.com/iluwatar/java-design-patterns/issues).
|
||||
- Utilisation de balises telles que `Performance`, `Gang of Four` ou `Data access`.
|
||||
- Utilisation des catégories de modèles, `Créatif`, `Comportemental` et autres.
|
||||
|
||||
J'espère que les solutions orientées objet présentées sur ce site vous seront utiles
|
||||
dans vos architectures et ayez autant de plaisir à les apprendre que nous en avons eu à les développer.
|
||||
|
||||
# Comment contribuer
|
||||
|
||||
Si vous souhaitez contribuer au projet, vous trouverez les informations pertinentes dans
|
||||
notre [wiki développeur](https://github.com/iluwatar/java-design-patterns/wiki). Nous aiderons
|
||||
vous et répondez à vos questions dans le [Gitter chatroom](https://gitter.im/iluwatar/java-design-patterns).
|
||||
|
||||
# Licence
|
||||
|
||||
Ce projet est concédé sous les termes de la licence MIT.
|
263
ko/README.md
@ -1,263 +0,0 @@
|
||||
<!-- the line below needs to be an empty line C: (its because kramdown isnt
|
||||
that smart and dearly wants an empty line before a heading to be able to
|
||||
display it as such, e.g. website) -->
|
||||
|
||||
# 자바로 구현된 디자인 패턴
|
||||
|
||||
[](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)[](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
|
||||
[](#contributors-)
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
# 소개
|
||||
|
||||
디자인 패턴은 프로그래머가 응용 프로그램이나 시스템을 디자인 할 때 일반적인 문제를 해결하는 데 사용할 수있는 가장 공식화 된 방법입니다.
|
||||
|
||||
디자인 패턴은 테스트되고 입증 된 개발 패러다임을 제공하여 개발 프로세스 속도를 높일 수 있습니다.
|
||||
|
||||
디자인 패턴을 재사용하면 주요 문제를 유발하는 미묘한 이슈들을 방지하는데 도움이 되며 또한 패턴에 익숙한 코더와 아키텍트의 코드 가독성도 향상됩니다.
|
||||
|
||||
# 시작하기
|
||||
|
||||
이 사이트는 Java 디자인 패턴을 보여줍니다. 이 솔루션은 오픈 소스 커뮤니티의 경험이 많은 프로그래머와 설계자가 개발했습니다. 패턴은 높은 수준의 설명이나 소스 코드를 통해 찾아 볼 수 있습니다. 소스 코드 예제는 잘 설명되어 있으며 특정 패턴을 구현하는 방법을 알려주는 프로그래밍 튜토리얼로 생각할 수 있습니다. 우리는 가장 널리 알려지고 실무에서 입증된 오픈 소스 Java 기술을 사용합니다.
|
||||
|
||||
자료를 살펴보기 전에 다양한 [소프트웨어 설계 원칙](https://java-design-patterns.com/principles/)을 숙지해야합니다.
|
||||
|
||||
모든 디자인은 가능한 한 단순해야합니다. 당신은 KISS, YAGNI로 시작해야하며, 원칙을 작동 할 수 있는 가장 단순한 일을 해야합니다. 복잡성과 패턴은 실용적인 확장성을 위해 필요할 때만 도입되어야합니다.
|
||||
|
||||
이러한 개념에 익숙해지면 다음 접근 방식 중 하나를 이용하여 [사용 가능한 디자인 패턴](https://java-design-patterns.com/patterns/)으로 드릴다운 할 수 있습니다.
|
||||
|
||||
- 이름으로 특정 패턴을 검색합니다. 찾을 수 없습니까? [여기](https://github.com/iluwatar/java-design-patterns/issues)에서 새 패턴을 보고하십시오.
|
||||
- `Performance`, `Gang of Four` 또는 `Data access` 태그 사용.
|
||||
- 패턴 카테고리, `Creational`, `Behavioral` 및 기타 사용
|
||||
|
||||
이 사이트에 제시된 객체 지향 솔루션이 여러분의 아키텍처에서 유용하고 우리가 개발 한 것만큼 재미있게 배우기를 바랍니다.
|
||||
|
||||
# 기여하는 방법
|
||||
|
||||
프로젝트에 기여할 의향이 있다면 [developer wiki](https://github.com/iluwatar/java-design-patterns/wiki)에서 관련 정보를 찾을 수 있습니다. [Gitter chatroom](https://gitter.im/iluwatar/java-design-patterns)에서 귀하를 돕고 질문에 답변 해 드리겠습니다.
|
||||
|
||||
# 특허
|
||||
|
||||
이 프로젝트는 MIT 라이센스 조건에 따라 라이센스가 부여됩니다.
|
||||
|
||||
# 기여자
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/iluwatar"><img src="https://avatars1.githubusercontent.com/u/582346?v=4" width="100px;" alt=""><br><sub><b>Ilkka Seppälä</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/amit1307"><img src="https://avatars0.githubusercontent.com/u/23420222?v=4" width="100px;" alt=""><br><sub><b>amit1307</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/npathai"><img src="https://avatars2.githubusercontent.com/u/1792515?v=4" width="100px;" alt=""><br><sub><b>Narendra Pathai</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/fluxw42"><img src="https://avatars1.githubusercontent.com/u/1545460?v=4" width="100px;" alt=""><br><sub><b>Jeroen Meulemeester</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://www.joemccarthy.co.uk"><img src="https://avatars0.githubusercontent.com/u/4526195?v=4" width="100px;" alt=""><br><sub><b>Joseph McCarthy</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/thomasoss"><img src="https://avatars1.githubusercontent.com/u/22516154?v=4" width="100px;" alt=""><br><sub><b>Thomas</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/anuragagarwal561994"><img src="https://avatars1.githubusercontent.com/u/6075379?v=4" width="100px;" alt=""><br><sub><b>Anurag Agarwal</b></sub></a></td>
|
||||
<td align="center"><a href="https://markusmo3.github.io"><img src="https://avatars1.githubusercontent.com/u/3317416?v=4" width="100px;" alt=""><br><sub><b>Markus Moser</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://twitter.com/i_sabiq"><img src="https://avatars1.githubusercontent.com/u/19510920?v=4" width="100px;" alt=""><br><sub><b>Sabiq Ihab</b></sub></a></td>
|
||||
<td align="center"><a href="http://inbravo.github.io"><img src="https://avatars3.githubusercontent.com/u/5253764?v=4" width="100px;" alt=""><br><sub><b>Amit Dixit</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/piyushchaudhari04"><img src="https://avatars3.githubusercontent.com/u/10268029?v=4" width="100px;" alt=""><br><sub><b>Piyush Kailash Chaudhari</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/joshzambales"><img src="https://avatars1.githubusercontent.com/u/8704552?v=4" width="100px;" alt=""><br><sub><b>joshzambales</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/Crossy147"><img src="https://avatars2.githubusercontent.com/u/7272996?v=4" width="100px;" alt=""><br><sub><b>Kamil Pietruszka</b></sub></a></td>
|
||||
<td align="center"><a href="http://cs.joensuu.fi/~zkhayda"><img src="https://avatars2.githubusercontent.com/u/660742?v=4" width="100px;" alt=""><br><sub><b>Zafar Khaydarov</b></sub></a></td>
|
||||
<td align="center"><a href="https://kemitix.github.io/"><img src="https://avatars1.githubusercontent.com/u/1147749?v=4" width="100px;" alt=""><br><sub><b>Paul Campbell</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/Argyro-Sioziou"><img src="https://avatars0.githubusercontent.com/u/22822639?v=4" width="100px;" alt=""><br><sub><b>Argyro Sioziou</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/TylerMcConville"><img src="https://avatars0.githubusercontent.com/u/4946449?v=4" width="100px;" alt=""><br><sub><b>TylerMcConville</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/saksham93"><img src="https://avatars1.githubusercontent.com/u/37399540?v=4" width="100px;" alt=""><br><sub><b>saksham93</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/nikhilbarar"><img src="https://avatars2.githubusercontent.com/u/37332144?v=4" width="100px;" alt=""><br><sub><b>nikhilbarar</b></sub></a></td>
|
||||
<td align="center"><a href="http://colinbut.com"><img src="https://avatars2.githubusercontent.com/u/10725674?v=4" width="100px;" alt=""><br><sub><b>Colin But</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/ruslanpa"><img src="https://avatars2.githubusercontent.com/u/1503411?v=4" width="100px;" alt=""><br><sub><b>Ruslan</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/JuhoKang"><img src="https://avatars1.githubusercontent.com/u/4745294?v=4" width="100px;" alt=""><br><sub><b>Juho Kang</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/dheeraj-mummareddy"><img src="https://avatars2.githubusercontent.com/u/7002230?v=4" width="100px;" alt=""><br><sub><b>Dheeraj Mummareddy</b></sub></a></td>
|
||||
<td align="center"><a href="https://www.bernardosulzbach.com"><img src="https://avatars0.githubusercontent.com/u/8271090?v=4" width="100px;" alt=""><br><sub><b>Bernardo Sulzbach</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/4lexis"><img src="https://avatars0.githubusercontent.com/u/19871727?v=4" width="100px;" alt=""><br><sub><b>Aleksandar Dudukovic</b></sub></a></td>
|
||||
<td align="center"><a href="https://www.yusufaytas.com"><img src="https://avatars2.githubusercontent.com/u/1049483?v=4" width="100px;" alt=""><br><sub><b>Yusuf Aytaş</b></sub></a></td>
|
||||
<td align="center"><a href="http://futurehomes.hu"><img src="https://avatars2.githubusercontent.com/u/1001491?v=4" width="100px;" alt=""><br><sub><b>Mihály Kuprivecz</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/kapinuss"><img src="https://avatars0.githubusercontent.com/u/17639945?v=4" width="100px;" alt=""><br><sub><b>Stanislav Kapinus</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/gvsharma"><img src="https://avatars1.githubusercontent.com/u/6648152?v=4" width="100px;" alt=""><br><sub><b>GVSharma</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/SrdjanPaunovic"><img src="https://avatars1.githubusercontent.com/u/22815104?v=4" width="100px;" alt=""><br><sub><b>Srđan Paunović</b></sub></a></td>
|
||||
<td align="center"><a href="https://sideris.xyz/"><img src="https://avatars3.githubusercontent.com/u/5484694?v=4" width="100px;" alt=""><br><sub><b>Petros G. Sideris</b></sub></a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/pramodgupta3/"><img src="https://avatars1.githubusercontent.com/u/2184241?v=4" width="100px;" alt=""><br><sub><b>Pramod Gupta</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://amarnath510.github.io/portfolio"><img src="https://avatars0.githubusercontent.com/u/4599623?v=4" width="100px;" alt=""><br><sub><b>Amarnath Chandana</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/Anurag870"><img src="https://avatars1.githubusercontent.com/u/6295975?v=4" width="100px;" alt=""><br><sub><b>Anurag870</b></sub></a></td>
|
||||
<td align="center"><a href="http://theerroris.me"><img src="https://avatars0.githubusercontent.com/u/1685953?v=4" width="100px;" alt=""><br><sub><b>Wes Gilleland</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/Harshrajsinh"><img src="https://avatars2.githubusercontent.com/u/22811531?v=4" width="100px;" alt=""><br><sub><b>Harshraj Thakor</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/MaVdbussche"><img src="https://avatars1.githubusercontent.com/u/26136934?v=4" width="100px;" alt=""><br><sub><b>Martin Vandenbussche</b></sub></a></td>
|
||||
<td align="center"><a href="https://alexsomai.com"><img src="https://avatars1.githubusercontent.com/u/5720977?v=4" width="100px;" alt=""><br><sub><b>Alexandru Somai</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/amogozov"><img src="https://avatars3.githubusercontent.com/u/7372215?v=4" width="100px;" alt=""><br><sub><b>Artur Mogozov</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/anthonycampbell"><img src="https://avatars3.githubusercontent.com/u/10249255?v=4" width="100px;" alt=""><br><sub><b>anthony</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://ccygnus.com/"><img src="https://avatars1.githubusercontent.com/u/9342724?v=4" width="100px;" alt=""><br><sub><b>Christian Cygnus</b></sub></a></td>
|
||||
<td align="center"><a href="https://about.me/dzmitryh"><img src="https://avatars2.githubusercontent.com/u/5390492?v=4" width="100px;" alt=""><br><sub><b>Dima Gubin</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/jjjimenez100"><img src="https://avatars3.githubusercontent.com/u/22243493?v=4" width="100px;" alt=""><br><sub><b>Joshua Jimenez</b></sub></a></td>
|
||||
<td align="center"><a href="http://about.me/kaiwinter"><img src="https://avatars0.githubusercontent.com/u/110982?v=4" width="100px;" alt=""><br><sub><b>Kai Winter</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/lbroman"><img src="https://avatars1.githubusercontent.com/u/86007?v=4" width="100px;" alt=""><br><sub><b>lbroman</b></sub></a></td>
|
||||
<td align="center"><a href="https://przemeknowak.com"><img src="https://avatars1.githubusercontent.com/u/3254609?v=4" width="100px;" alt=""><br><sub><b>Przemek</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/prafful1"><img src="https://avatars0.githubusercontent.com/u/14350274?v=4" width="100px;" alt=""><br><sub><b>Prafful Agarwal</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/sankypanhale"><img src="https://avatars1.githubusercontent.com/u/6478783?v=4" width="100px;" alt=""><br><sub><b>Sanket Panhale</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/staillebois"><img src="https://avatars0.githubusercontent.com/u/23701200?v=4" width="100px;" alt=""><br><sub><b>staillebois</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/valdar-hu"><img src="https://avatars3.githubusercontent.com/u/17962817?v=4" width="100px;" alt=""><br><sub><b>Krisztián Nagy</b></sub></a></td>
|
||||
<td align="center"><a href="https://www.vanogrid.com"><img src="https://avatars0.githubusercontent.com/u/4307918?v=4" width="100px;" alt=""><br><sub><b>Alexander Ivanov</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/yosfik"><img src="https://avatars3.githubusercontent.com/u/4850270?v=4" width="100px;" alt=""><br><sub><b>Yosfik Alqadri</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/7agustibm"><img src="https://avatars0.githubusercontent.com/u/8149332?v=4" width="100px;" alt=""><br><sub><b>Agustí Becerra Milà</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/Juaanma"><img src="https://avatars3.githubusercontent.com/u/7390500?v=4" width="100px;" alt=""><br><sub><b>Juan Manuel Suárez</b></sub></a></td>
|
||||
<td align="center"><a href="http://www.devsedge.net/"><img src="https://avatars0.githubusercontent.com/u/9956006?v=4" width="100px;" alt=""><br><sub><b>Luigi Cortese</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/Rzeposlaw"><img src="https://avatars2.githubusercontent.com/u/18425745?v=4" width="100px;" alt=""><br><sub><b>Katarzyna Rzepecka</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://adamski.pro"><img src="https://avatars1.githubusercontent.com/u/6537430?v=4" width="100px;" alt=""><br><sub><b>adamski.pro</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/baislsl"><img src="https://avatars0.githubusercontent.com/u/17060584?v=4" width="100px;" alt=""><br><sub><b>Shengli Bai</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/besok"><img src="https://avatars2.githubusercontent.com/u/29834592?v=4" width="100px;" alt=""><br><sub><b>Boris</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/dmitraver"><img src="https://avatars3.githubusercontent.com/u/1798156?v=4" width="100px;" alt=""><br><sub><b>Dmitry Avershin</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/fanofxiaofeng"><img src="https://avatars0.githubusercontent.com/u/3983683?v=4" width="100px;" alt=""><br><sub><b>靳阳</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/hoangnam2261"><img src="https://avatars2.githubusercontent.com/u/31692990?v=4" width="100px;" alt=""><br><sub><b>hoangnam2261</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/jarpit96"><img src="https://avatars2.githubusercontent.com/u/10098713?v=4" width="100px;" alt=""><br><sub><b>Arpit Jain</b></sub></a></td>
|
||||
<td align="center"><a href="http://joningi.net"><img src="https://avatars2.githubusercontent.com/u/6115148?v=4" width="100px;" alt=""><br><sub><b>Jón Ingi Sveinbjörnsson</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/kirill-vlasov"><img src="https://avatars3.githubusercontent.com/u/16112495?v=4" width="100px;" alt=""><br><sub><b>Kirill Vlasov</b></sub></a></td>
|
||||
<td align="center"><a href="http://mitchell-irvin.com"><img src="https://avatars0.githubusercontent.com/u/16233245?v=4" width="100px;" alt=""><br><sub><b>Mitchell Irvin</b></sub></a></td>
|
||||
<td align="center"><a href="https://ranjeet-floyd.github.io"><img src="https://avatars0.githubusercontent.com/u/1992972?v=4" width="100px;" alt=""><br><sub><b>Ranjeet</b></sub></a></td>
|
||||
<td align="center"><a href="https://alwayswithme.github.io"><img src="https://avatars3.githubusercontent.com/u/3234786?v=4" width="100px;" alt=""><br><sub><b>PhoenixYip</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/MSaifAsif"><img src="https://avatars1.githubusercontent.com/u/6280554?v=4" width="100px;" alt=""><br><sub><b>M Saif Asif</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/kanwarpreet25"><img src="https://avatars0.githubusercontent.com/u/39183641?v=4" width="100px;" alt=""><br><sub><b>kanwarpreet25</b></sub></a></td>
|
||||
<td align="center"><a href="http://leonmak.me"><img src="https://avatars3.githubusercontent.com/u/13071508?v=4" width="100px;" alt=""><br><sub><b>Leon Mak</b></sub></a></td>
|
||||
<td align="center"><a href="http://www.wramdemark.se"><img src="https://avatars2.githubusercontent.com/u/7052193?v=4" width="100px;" alt=""><br><sub><b>Per Wramdemark</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/waisuan"><img src="https://avatars2.githubusercontent.com/u/10975700?v=4" width="100px;" alt=""><br><sub><b>Evan Sia Wai Suan</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/AnaghaSasikumar"><img src="https://avatars2.githubusercontent.com/u/42939261?v=4" width="100px;" alt=""><br><sub><b>AnaghaSasikumar</b></sub></a></td>
|
||||
<td align="center"><a href="https://christofferh.com"><img src="https://avatars1.githubusercontent.com/u/767643?v=4" width="100px;" alt=""><br><sub><b>Christoffer Hamberg</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/dgruntz"><img src="https://avatars0.githubusercontent.com/u/1516800?v=4" width="100px;" alt=""><br><sub><b>Dominik Gruntz</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://bitbucket.org/hannespernpeintner/"><img src="https://avatars3.githubusercontent.com/u/1679437?v=4" width="100px;" alt=""><br><sub><b>Hannes</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/leogtzr"><img src="https://avatars0.githubusercontent.com/u/1211969?v=4" width="100px;" alt=""><br><sub><b>Leo Gutiérrez Ramírez</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/npczwh"><img src="https://avatars0.githubusercontent.com/u/14066422?v=4" width="100px;" alt=""><br><sub><b>Zhang WH</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/oconnelc"><img src="https://avatars0.githubusercontent.com/u/1112973?v=4" width="100px;" alt=""><br><sub><b>Christopher O'Connell</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/giorgosmav21"><img src="https://avatars2.githubusercontent.com/u/22855493?v=4" width="100px;" alt=""><br><sub><b>George Mavroeidis</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/hbothra15"><img src="https://avatars1.githubusercontent.com/u/7418012?v=4" width="100px;" alt=""><br><sub><b>Hemant Bothra</b></sub></a></td>
|
||||
<td align="center"><a href="https://www.kevinpeters.net/about/"><img src="https://avatars1.githubusercontent.com/u/12736734?v=4" width="100px;" alt=""><br><sub><b>Kevin Peters</b></sub></a></td>
|
||||
<td align="center"><a href="https://llorllale.github.io/"><img src="https://avatars1.githubusercontent.com/u/2019896?v=4" width="100px;" alt=""><br><sub><b>George Aristy</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/mookkiah"><img src="https://avatars1.githubusercontent.com/u/8975264?v=4" width="100px;" alt=""><br><sub><b>Mahendran Mookkiah</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/Azureyjt"><img src="https://avatars2.githubusercontent.com/u/18476317?v=4" width="100px;" alt=""><br><sub><b>Azureyjt</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/vehpsr"><img src="https://avatars2.githubusercontent.com/u/3133265?v=4" width="100px;" alt=""><br><sub><b>gans</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/ThatGuyWithTheHat"><img src="https://avatars0.githubusercontent.com/u/24470582?v=4" width="100px;" alt=""><br><sub><b>Matt</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/gopinathlangote/"><img src="https://avatars2.githubusercontent.com/u/10210778?v=4" width="100px;" alt=""><br><sub><b>Gopinath Langote</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/hoswey"><img src="https://avatars3.githubusercontent.com/u/3689445?v=4" width="100px;" alt=""><br><sub><b>Hoswey</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/amit2103"><img src="https://avatars3.githubusercontent.com/u/7566692?v=4" width="100px;" alt=""><br><sub><b>Amit Pandey</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/gwildor28"><img src="https://avatars0.githubusercontent.com/u/16000365?v=4" width="100px;" alt=""><br><sub><b>gwildor28</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://t.me/paul_docker"><img src="https://avatars1.githubusercontent.com/u/2404785?v=4" width="100px;" alt=""><br><sub><b>田浩</b></sub></a></td>
|
||||
<td align="center"><a href="https://twitter.com/StPitsios"><img src="https://avatars1.githubusercontent.com/u/6773603?v=4" width="100px;" alt=""><br><sub><b>Stamatis Pitsios</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/qza"><img src="https://avatars3.githubusercontent.com/u/233149?v=4" width="100px;" alt=""><br><sub><b>qza</b></sub></a></td>
|
||||
<td align="center"><a href="http://tschis.github.io"><img src="https://avatars1.githubusercontent.com/u/20662669?v=4" width="100px;" alt=""><br><sub><b>Rodolfo Forte</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/ankurkaushal"><img src="https://avatars2.githubusercontent.com/u/2236616?v=4" width="100px;" alt=""><br><sub><b>Ankur Kaushal</b></sub></a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/ovidijus-okinskas/"><img src="https://avatars0.githubusercontent.com/u/20372387?v=4" width="100px;" alt=""><br><sub><b>Ovidijus Okinskas</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/robertt240"><img src="https://avatars1.githubusercontent.com/u/9137432?v=4" width="100px;" alt=""><br><sub><b>Robert Kasperczyk</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/trautonen"><img src="https://avatars3.githubusercontent.com/u/1641063?v=4" width="100px;" alt=""><br><sub><b>Tapio Rautonen</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://vk.com/yuri.orlov"><img src="https://avatars0.githubusercontent.com/u/1595733?v=4" width="100px;" alt=""><br><sub><b>Yuri Orlov</b></sub></a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/varunu28/"><img src="https://avatars0.githubusercontent.com/u/7676016?v=4" width="100px;" alt=""><br><sub><b>Varun Upadhyay</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/PalAditya"><img src="https://avatars2.githubusercontent.com/u/25523604?v=4" width="100px;" alt=""><br><sub><b>Aditya Pal</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/grzesiekkedzior"><img src="https://avatars3.githubusercontent.com/u/23739158?v=4" width="100px;" alt=""><br><sub><b>grzesiekkedzior</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/sivasubramanim"><img src="https://avatars2.githubusercontent.com/u/51107434?v=4" width="100px;" alt=""><br><sub><b>Sivasubramani M</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/d4gg4d"><img src="https://avatars2.githubusercontent.com/u/99457?v=4" width="100px;" alt=""><br><sub><b>Sami Airaksinen</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/vertti"><img src="https://avatars0.githubusercontent.com/u/557751?v=4" width="100px;" alt=""><br><sub><b>Janne Sinivirta</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/Bobo1239"><img src="https://avatars1.githubusercontent.com/u/2302947?v=4" width="100px;" alt=""><br><sub><b>Boris-Chengbiao Zhou</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://jahhein.github.io"><img src="https://avatars2.githubusercontent.com/u/10779515?v=4" width="100px;" alt=""><br><sub><b>Jacob Hein</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/iamrichardjones"><img src="https://avatars3.githubusercontent.com/u/14842151?v=4" width="100px;" alt=""><br><sub><b>Richard Jones</b></sub></a></td>
|
||||
<td align="center"><a href="https://rachelcarmena.github.io"><img src="https://avatars0.githubusercontent.com/u/22792183?v=4" width="100px;" alt=""><br><sub><b>Rachel M. Carmena</b></sub></a></td>
|
||||
<td align="center"><a href="https://zd-zero.github.io"><img src="https://avatars0.githubusercontent.com/u/21978370?v=4" width="100px;" alt=""><br><sub><b>Zaerald Denze Lungos</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://webpro.nl"><img src="https://avatars1.githubusercontent.com/u/456426?v=4" width="100px;" alt=""><br><sub><b>Lars Kappert</b></sub></a></td>
|
||||
<td align="center"><a href="https://xiaod.info"><img src="https://avatars2.githubusercontent.com/u/21277644?v=4" width="100px;" alt=""><br><sub><b>Mike Liu</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/charlesfinley"><img src="https://avatars1.githubusercontent.com/u/6307904?v=4" width="100px;" alt=""><br><sub><b>Matt Dolan</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/MananS77"><img src="https://avatars3.githubusercontent.com/u/21033516?v=4" width="100px;" alt=""><br><sub><b>Manan</b></sub></a></td>
|
||||
</tr>
|
||||
<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></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></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></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></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/ashish-trivedi-218379135/"><img src="https://avatars3.githubusercontent.com/u/23194128?v=4" width="100px;" alt=""><br><sub><b>Ashish Trivedi</b></sub></a></td>
|
||||
<td align="center"><a href="https://rayyounghong.com"><img src="https://avatars1.githubusercontent.com/u/41055099?v=4" width="100px;" alt=""><br><sub><b>洪月阳</b></sub></a></td>
|
||||
<td align="center"><a href="https://xdvrx1.github.io/"><img src="https://avatars0.githubusercontent.com/u/47092464?v=4" width="100px;" alt=""><br><sub><b>xdvrx1</b></sub></a></td>
|
||||
<td align="center"><a href="http://subho.xyz"><img src="https://avatars0.githubusercontent.com/u/13291222?v=4" width="100px;" alt=""><br><sub><b>Subhrodip Mohanta</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/nahteb"><img src="https://avatars3.githubusercontent.com/u/13121570?v=4" width="100px;" alt=""><br><sub><b>Bethan Palmer</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/ToxicDreamz"><img src="https://avatars0.githubusercontent.com/u/45225562?v=4" width="100px;" alt=""><br><sub><b>Toxic Dreamz</b></sub></a></td>
|
||||
<td align="center"><a href="http://www.edycutjong.com"><img src="https://avatars1.githubusercontent.com/u/1098102?v=4" width="100px;" alt=""><br><sub><b>Edy Cu Tjong</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/mkrzywanski"><img src="https://avatars0.githubusercontent.com/u/15279585?v=4" width="100px;" alt=""><br><sub><b>Michał Krzywański</b></sub></a></td>
|
||||
</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></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></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></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></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></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-enable -->
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
@ -1,134 +0,0 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Adapter
|
||||
folder: adapter
|
||||
permalink: "/patterns/adapter/"
|
||||
categories: Structural
|
||||
tags:
|
||||
- Gang of Four
|
||||
---
|
||||
|
||||
## 또한 ~으로 알려진
|
||||
|
||||
Wrapper
|
||||
|
||||
## 의도
|
||||
|
||||
클래스의 인터페이스를 클라이언트가 기대하는 다른 인터페이스로 변환합니다. adapter를 사용하면 호환되지 않는 인터페이스로 인해 같이 쓸 수 없는 클래스를 함께 작동 할 수 있습니다.
|
||||
|
||||
## 설명
|
||||
|
||||
예시
|
||||
|
||||
> 메모리 카드에 몇 장의 사진이 있고 컴퓨터로 전송해야한다고 생각하십시오. 이들을 전송하려면 컴퓨터에 메모리 카드를 연결할 수 있도록 컴퓨터 포트와 호환되는 어댑터가 필요합니다. 이 경우 카드 리더는 어댑터입니다. 또 다른 예는 유명한 전원 어댑터입니다. 세 갈래 플러그는 두 갈래 콘센트에 연결할 수 없습니다. 두 갈래 콘센트와 호환되는 전원 어댑터를 사용해야합니다. 또 다른 예는 한 사람이 말한 단어를 다른 사람에게 번역하는 번역가입니다.
|
||||
|
||||
평범하게 말하자면
|
||||
|
||||
> adapter 패턴을 사용하면 호환되지 않는 개체를 adapter에 연결하여 다른 클래스와 호환되도록 할 수 있습니다.
|
||||
|
||||
Wikipedia 말에 의하면
|
||||
|
||||
> 소프트웨어 엔지니어링에서 adapter 패턴은 기존 클래스의 인터페이스를 다른 인터페이스로 사용할 수 있도록 하는 소프트웨어 디자인 패턴입니다. 소스 코드를 수정하지 않고 기존 클래스가 다른 클래스와 함께 작동하도록 만드는 데 자주 사용됩니다.
|
||||
|
||||
**프로그램 코드 예제**
|
||||
|
||||
조정 보트만 사용할 수 있고 전혀 항해할 수 없는 선장을 생각해보십시오.
|
||||
|
||||
먼저 `RowingBoat` 및 `FishingBoat` 인터페이스가 있습니다.
|
||||
|
||||
```java
|
||||
public interface RowingBoat {
|
||||
void row();
|
||||
}
|
||||
|
||||
public class FishingBoat {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoat.class);
|
||||
public void sail() {
|
||||
LOGGER.info("The fishing boat is sailing");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
그리고 선장은 `RowingBoat` 인터페이스를 이동할 수 있게 구현했습니다.
|
||||
|
||||
```java
|
||||
public class Captain {
|
||||
|
||||
private final RowingBoat rowingBoat;
|
||||
// default constructor and setter for rowingBoat
|
||||
public Captain(RowingBoat rowingBoat) {
|
||||
this.rowingBoat = rowingBoat;
|
||||
}
|
||||
|
||||
public void row() {
|
||||
rowingBoat.row();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
이제 해적이오고 있고 우리 선장이 탈출해야하는데 어선만 있습니다. 선장이 조정 보트 기술로 어선을 조작 할 수있는 adapter를 만들어야합니다.
|
||||
|
||||
```java
|
||||
public class FishingBoatAdapter implements RowingBoat {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoatAdapter.class);
|
||||
|
||||
private final FishingBoat boat;
|
||||
|
||||
public FishingBoatAdapter() {
|
||||
boat = new FishingBoat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void row() {
|
||||
boat.sail();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
이제 `Captain` 은 `FishingBoat` 를 사용하여 해적을 탈출 할 수 있습니다.
|
||||
|
||||
```java
|
||||
var captain = new Captain(new FishingBoatAdapter());
|
||||
captain.row();
|
||||
```
|
||||
|
||||
## 클레스 다이어그램
|
||||
|
||||

|
||||
|
||||
## 적용 가능성
|
||||
|
||||
다음과 같은 경우 adapter 패턴을 사용합니다.
|
||||
|
||||
- 기존 클래스를 사용 하려는데 해당 인터페이스가 필요한 클래스와 일치하지 않습니다.
|
||||
- 관련이 없거나 예상치 못한 클래스, 즉 호환되는 인터페이스가 반드시 필요하지 않은 클래스와 협력하는 재사용 가능한 클래스를 만들고 싶습니다.
|
||||
- 기존의 여러 하위 클래스를 사용해야하지만 모든 하위 클래스를 하위 클래스로 지정하여 인터페이스를 조정하는 것은 비현실적입니다. 개체 adapter는 부모 클래스의 인터페이스를 조정할 수 있습니다.
|
||||
- 타사 라이브러리를 사용하는 대부분의 응용 프로그램은 adapter를 응용 프로그램과 타사 라이브러리 사이의 중간 계층으로 사용하여 라이브러리에서 응용 프로그램을 분리합니다. 다른 라이브러리를 사용해야하는 경우 애플리케이션 코드를 변경할 필요없이 새 라이브러리 용 adapter만 필요합니다.
|
||||
|
||||
## 결과 :
|
||||
|
||||
클래스 및 개체 adapter에는 서로 다른 장단점이 있습니다. <br>클래스 adapter
|
||||
|
||||
- 구체적인 Adaptee 클래스를 커밋하여 Adaptee를 Target에 적용합니다. 결과적으로 클래스와 모든 하위 클래스를 조정하려는 경우 클래스 adapter가 작동하지 않습니다.
|
||||
- adapter는 Adaptee의 하위 클래스이기 때문에 Adaptee의 일부 동작을 오버라이드합니다.
|
||||
- 하나의 객체만 생성하고 adaptee를 얻기위해 위해 추가 포인터 간접 지정이 필요하지 않습니다.
|
||||
|
||||
개체 adapter
|
||||
|
||||
- 하나의 adapter가 많은 Adaptees, 즉 Adaptee 자체와 모든 하위 클래스 (있는 경우)와 함께 작동하도록합시다. adapter는 한 번에 모든 어댑터에 기능을 추가 할 수도 있습니다.
|
||||
- Adaptee 동작을 오버라이드하기가 더 어렵습니다. Adaptee를 서브 클래싱하고 어댑터가 Adaptee 자체가 아닌 서브 클래스를 참조하도록 해야합니다.
|
||||
|
||||
## 실제 사례
|
||||
|
||||
- [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)
|
||||
- [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)
|
||||
- [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-)
|
||||
- [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-)
|
||||
|
||||
## 크레딧
|
||||
|
||||
- [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)
|
||||
- [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)
|
||||
- [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)
|
||||
- [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)
|
@ -1,128 +0,0 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Factory
|
||||
folder: factory
|
||||
permalink: "/patterns/factory/"
|
||||
categories: Creational
|
||||
tags:
|
||||
- Gang of Four
|
||||
---
|
||||
|
||||
## 또한 ~으로 알려진
|
||||
|
||||
- Simple Factory
|
||||
- Static Factory Method
|
||||
|
||||
## 의도
|
||||
|
||||
구현 논리를 숨기고 클라이언트 코드가 새 객체를 초기화하는 대신 사용에 집중하도록하기 위해 factory라는 클래스에 캡슐화 된 정적 메서드를 제공합니다.
|
||||
|
||||
## 설명
|
||||
|
||||
예시
|
||||
|
||||
> SQLServer에 연결된 웹 응용 프로그램이 있지만 이제 Oracle로 전환하려고 합니다. 기존 소스 코드를 수정하지 않고 이를 수행하려면 주어진 데이터베이스에 대한 연결을 생성하기 위해 정적 메서드를 호출 할 수 있는 Simple Factory 패턴을 구현해야합니다.
|
||||
|
||||
Wikipedia 말에 의하면
|
||||
|
||||
> factory는 다른 객체를 생성하기위한 객체입니다. 공식적으로 factory는 다양한 프로토 타입 또는 클래스의 객체를 반환하는 함수 또는 메서드입니다.
|
||||
|
||||
**프로그램 코드 예제**
|
||||
|
||||
우리는 인터페이스 `Car` 와 두 가지 구현 `Ford` 와 `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;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
열거형은 우리가 지원하는 자동차 유형을 나타냅니다 ( `Ford` 및 `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;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
그런 다음 factory 클래스 `CarsFactory` 캡슐화 된 자동차 객체를 만드는 정적 메서드 `getCar` 가 있습니다.
|
||||
|
||||
```java
|
||||
public class CarsFactory {
|
||||
|
||||
public static Car getCar(CarType type) {
|
||||
return type.getConstructor().get();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
이제 클라이언트 코드에서 factory 클래스를 사용하여 다양한 유형의 자동차를 만들 수 있습니다.
|
||||
|
||||
```java
|
||||
var car1 = CarsFactory.getCar(CarType.FORD);
|
||||
var car2 = CarsFactory.getCar(CarType.FERRARI);
|
||||
LOGGER.info(car1.getDescription());
|
||||
LOGGER.info(car2.getDescription());;
|
||||
```
|
||||
|
||||
프로그램 출력 :
|
||||
|
||||
```java
|
||||
This is Ford.
|
||||
This Ferrari.
|
||||
```
|
||||
|
||||
## 클래스 다이어그램
|
||||
|
||||

|
||||
|
||||
## 적용 가능성
|
||||
|
||||
객체 생성 및 관리 방법이 아닌 객체 생성에만 관심이있을 때 Simple Factory 패턴을 사용합니다.
|
||||
|
||||
장점
|
||||
|
||||
- 모든 객체 생성을 한곳에 유지하고 코드베이스에 '새'키 값이 확산되는 것을 방지합니다.
|
||||
- 느슨하게 결합 된 코드를 작성할 수 있습니다. 주요 장점 중 일부는 더 나은 테스트 가능성, 이해하기 쉬운 코드, 교체 가능한 구성 요소, 확장성 및 격리된 기능을 포함합니다.
|
||||
|
||||
단점
|
||||
|
||||
- 코드는 생각보다 복잡해집니다.
|
||||
|
||||
## 관련 패턴
|
||||
|
||||
- [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/)
|
@ -1,165 +0,0 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Observer
|
||||
folder: observer
|
||||
permalink: "/patterns/observer/"
|
||||
categories: Behavioral
|
||||
tags:
|
||||
- Gang Of Four
|
||||
- Reactive
|
||||
---
|
||||
|
||||
## 또한 ~으로 알려진
|
||||
|
||||
Dependents, Publish-Subscribe
|
||||
|
||||
## 의도
|
||||
|
||||
하나의 개체가 상태를 변경하면 모든 종속 항목에 알림이 전송되고 자동으로 업데이트 되도록 개체간의 일대 다 종속성을 정의합니다.
|
||||
|
||||
## 설명
|
||||
|
||||
예시
|
||||
|
||||
> 멀리 떨어진 땅에는 호빗과 오크 종족이 살고 있습니다. 둘 다 대부분 야외에 있으므로 날씨 변화를 면밀히 따릅니다. 끊임없이 날씨를 관찰하고 있다고 말할 수 있습니다.
|
||||
|
||||
평범하게 말하자면
|
||||
|
||||
> observer로 등록하여 개체의 상태 변경을 수신합니다.
|
||||
|
||||
Wikipedia 말에 의하면
|
||||
|
||||
> observer 패턴은 주제라고하는 객체가 observer라고 하는 종속 항목 목록을 유지하고 일반적으로 메서드 중 하나를 호출하여 상태 변경을 자동으로 알리는 소프트웨어 디자인 패턴입니다.
|
||||
|
||||
**프로그램 코드 예제**
|
||||
|
||||
먼저 `WeatherObserver` 인터페이스와 우리의 종족 `Orcs` 와 `Hobbits` 소개하겠습니다.
|
||||
|
||||
```java
|
||||
public interface WeatherObserver {
|
||||
|
||||
void update(WeatherType currentWeather);
|
||||
}
|
||||
|
||||
public class Orcs implements WeatherObserver {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Orcs.class);
|
||||
|
||||
@Override
|
||||
public void update(WeatherType currentWeather) {
|
||||
LOGGER.info("The orcs are facing " + currentWeather.getDescription() + " weather now");
|
||||
}
|
||||
}
|
||||
|
||||
public class Hobbits implements WeatherObserver {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Hobbits.class);
|
||||
|
||||
@Override
|
||||
public void update(WeatherType currentWeather) {
|
||||
switch (currentWeather) {
|
||||
LOGGER.info("The hobbits are facing " + currentWeather.getDescription() + " weather now");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
그리고 끊임없이 변화하는 `Weather` 가 있습니다.
|
||||
|
||||
```java
|
||||
public class Weather {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Weather.class);
|
||||
|
||||
private WeatherType currentWeather;
|
||||
private final List<WeatherObserver> observers;
|
||||
|
||||
public Weather() {
|
||||
observers = new ArrayList<>();
|
||||
currentWeather = WeatherType.SUNNY;
|
||||
}
|
||||
|
||||
public void addObserver(WeatherObserver obs) {
|
||||
observers.add(obs);
|
||||
}
|
||||
|
||||
public void removeObserver(WeatherObserver obs) {
|
||||
observers.remove(obs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes time pass for weather.
|
||||
*/
|
||||
public void timePasses() {
|
||||
var enumValues = WeatherType.values();
|
||||
currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length];
|
||||
LOGGER.info("The weather changed to {}.", currentWeather);
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
private void notifyObservers() {
|
||||
for (var obs : observers) {
|
||||
obs.update(currentWeather);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
여기에 전체 예제가 있습니다.
|
||||
|
||||
```java
|
||||
var weather = new Weather();
|
||||
weather.addObserver(new Orcs());
|
||||
weather.addObserver(new Hobbits());
|
||||
weather.timePasses();
|
||||
weather.timePasses();
|
||||
weather.timePasses();
|
||||
weather.timePasses();
|
||||
```
|
||||
|
||||
프로그램 출력 :
|
||||
|
||||
```
|
||||
The weather changed to rainy.
|
||||
The orcs are facing rainy weather now
|
||||
The hobbits are facing rainy weather now
|
||||
The weather changed to windy.
|
||||
The orcs are facing windy weather now
|
||||
The hobbits are facing windy weather now
|
||||
The weather changed to cold.
|
||||
The orcs are facing cold weather now
|
||||
The hobbits are facing cold weather now
|
||||
The weather changed to sunny.
|
||||
The orcs are facing sunny weather now
|
||||
The hobbits are facing sunny weather now
|
||||
```
|
||||
|
||||
## 클래스 다이어그램
|
||||
|
||||

|
||||
|
||||
## 적용 가능성
|
||||
|
||||
다음 상황에서 관찰자 패턴을 사용하십시오.
|
||||
|
||||
- 추상화에 두 가지 측면이 있을 때 하나는 다른 하나에 종속됩니다. 이러한 측면을 별도의 개체에 캡슐화하면 독립적으로 변경하고 재사용 할 수 있습니다.
|
||||
- 한 개체를 변경하려면 얼마나 다른 개체를 변경해야 하는지 알 수 없는 경우입니다.
|
||||
- 개체가 다른 개체가 누구인지 가정하지 않고 알릴 수 있어야하는 경우. 즉, 개체가 단단히 결합되는 것을 원하지 않습니다.
|
||||
|
||||
## 일반적인 사용 사례
|
||||
|
||||
- 한 개체를 변경하면 다른 개체도 변경됩니다.
|
||||
|
||||
## 실제 사례
|
||||
|
||||
- [java.util.Observer](http://docs.oracle.com/javase/8/docs/api/java/util/Observer.html)
|
||||
- [java.util.EventListener](http://docs.oracle.com/javase/8/docs/api/java/util/EventListener.html)
|
||||
- [javax.servlet.http.HttpSessionBindingListener](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionBindingListener.html)
|
||||
- [RxJava](https://github.com/ReactiveX/RxJava)
|
||||
|
||||
## 크레딧
|
||||
|
||||
- [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)
|
||||
- [Java Generics and Collections](https://www.amazon.com/gp/product/0596527756/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596527756&linkCode=as2&tag=javadesignpat-20&linkId=246e5e2c26fe1c3ada6a70b15afcb195)
|
||||
- [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)
|
||||
- [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)
|
@ -1,87 +0,0 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Prototype
|
||||
folder: prototype
|
||||
permalink: "/patterns/prototype/"
|
||||
categories: Creational
|
||||
tags:
|
||||
- Gang Of Four
|
||||
- Instantiation
|
||||
---
|
||||
|
||||
## 의도
|
||||
|
||||
prototype 인스턴스를 사용하여 만들 개체의 종류를 지정하고 prototype을 복사하여 새 개체를 만듭니다.
|
||||
|
||||
## 설명
|
||||
|
||||
먼저 성능 이점을 얻기 위해 prototype 패턴이 사용되지 않는다는 점에 유의해야합니다. 오직 prototype 인스턴스에서 새 개체를 만드는 데만 사용됩니다.
|
||||
|
||||
예시
|
||||
|
||||
> 복제된 양인 돌리에 대해 기억나십니까? 자세한 내용은 다루지 않겠습니다만 여기서 핵심은 복제에 관한 것입니다.
|
||||
|
||||
평범한 말하자면
|
||||
|
||||
> 복제를 통해 기존 개체를 기반으로 개체를 만듭니다.
|
||||
|
||||
Wikipedia 말에 의하면
|
||||
|
||||
> prototype 패턴은 소프트웨어 개발에서 생성 디자인 패턴입니다. 생성 할 개체의 유형이 새 개체를 생성하기 위해 복제되는 prototype 인스턴스에 의해 결정될 때 사용됩니다.
|
||||
|
||||
간단히 말해, 객체를 처음부터 만들고 설정하는 문제를 겪는 대신 기존 객체의 복사본을 만들어 필요에 맞게 수정할 수 있습니다.
|
||||
|
||||
**프로그램 코드 예제**
|
||||
|
||||
Java에서는 `Cloneable` 을 구현하고 `Object` 에서 `clone` 을 오버라이딩하여 쉽게 수행 할 수 있습니다.
|
||||
|
||||
```java
|
||||
class Sheep implements Cloneable {
|
||||
private String name;
|
||||
public Sheep(String name) { this.name = name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
public String getName() { return name; }
|
||||
@Override
|
||||
public Sheep clone() {
|
||||
try {
|
||||
return (Sheep)super.clone();
|
||||
} catch(CloneNotSuportedException) {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
그런 다음 아래와 같이 복제할 수 있습니다.
|
||||
|
||||
```java
|
||||
var original = new Sheep("Jolly");
|
||||
System.out.println(original.getName()); // Jolly
|
||||
|
||||
// Clone and modify what is required
|
||||
var cloned = original.clone();
|
||||
cloned.setName("Dolly");
|
||||
System.out.println(cloned.getName()); // Dolly
|
||||
```
|
||||
|
||||
## 클래스 다이어그램
|
||||
|
||||

|
||||
|
||||
## 적용 가능성
|
||||
|
||||
시스템이 제품의 생성, 구성, 표현 및 표현 방식에 독립적이어야 할 때 prototype 패턴을 사용
|
||||
|
||||
- 인스턴스화할 클래스가 런타임에 지정되는 경우 (예 : 동적 로딩)
|
||||
- 제품의 클래스 계층 구조와 유사한 팩토리의 클래스 계층 구조 구축을 방지해야할 경우
|
||||
- 클래스의 인스턴스가 몇 가지 다른 상태 조합 중 하나만 가질 수 있는 경우. 적절한 상태로 매번 클래스를 수동으로 인스턴스화하는 것보다 해당하는 수의 prototype을 설치하고 복제하는 것이 더 편리 할 수 있습니다.
|
||||
- 복제에 비해 개체 생성 비용이 많이 드는 경우.
|
||||
|
||||
## 실제 사례
|
||||
|
||||
- [java.lang.Object#clone()](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone%28%29)
|
||||
|
||||
## 크레딧
|
||||
|
||||
- [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)
|
||||
- [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)
|
@ -1,84 +0,0 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Singleton
|
||||
folder: singleton
|
||||
permalink: "/patterns/singleton/"
|
||||
categories: Creational
|
||||
tags:
|
||||
- Gang of Four
|
||||
---
|
||||
|
||||
## 의도
|
||||
|
||||
클래스에 인스턴스가 하나만 있는지 확인하고 이에 대한 전역 access point을 제공합니다.
|
||||
|
||||
## 설명
|
||||
|
||||
예시
|
||||
|
||||
> 마법사들이 마법을 연구하는 상아탑은 단 하나뿐입니다. 마법사는 항상 동일한 마법의 상아탑을 사용합니다. 여기서 상아탑은 singleton입니다.
|
||||
|
||||
평범하게 말하자면
|
||||
|
||||
> 특정 클래스의 개체가 하나만 생성되도록합니다.
|
||||
|
||||
Wikipedia 말에 의하면
|
||||
|
||||
> 소프트웨어 엔지니어링에서 singleton 패턴은 클래스의 인스턴스화를 하나의 객체로 제한하는 소프트웨어 디자인 패턴입니다. 이는 시스템 전체에서 작업을 조정하는 데 정확히 하나의 개체가 필요할 때 유용합니다.
|
||||
|
||||
**프로그램 코드 예제**
|
||||
|
||||
Joshua Bloch, Effective Java 2nd Edition p.18
|
||||
|
||||
> 단일 요소 열거형은 singleton을 구현하는 가장 좋은 방법입니다.
|
||||
|
||||
```java
|
||||
public enum EnumIvoryTower {
|
||||
INSTANCE
|
||||
}
|
||||
```
|
||||
|
||||
그런 다음 사용하려면 :
|
||||
|
||||
```java
|
||||
var enumIvoryTower1 = EnumIvoryTower.INSTANCE;
|
||||
var enumIvoryTower2 = EnumIvoryTower.INSTANCE;
|
||||
assertEquals(enumIvoryTower1, enumIvoryTower2); // true
|
||||
```
|
||||
|
||||
## 클래스 다이어그램
|
||||
|
||||

|
||||
|
||||
## 적용 가능성
|
||||
|
||||
다음과 같은 경우 Singleton 패턴을 사용합니다.
|
||||
|
||||
- 정확히 하나의 클래스 인스턴스가 있어야하며 잘 알려진 access point에서 클라이언트에 접근할 수 있어야합니다.
|
||||
- 단일 인스턴스가 서브 클래싱으로 확장 가능해야하고 클라이언트가 코드를 수정하지 않고 확장 인스턴스를 사용할 수 있어야 하는 경우
|
||||
|
||||
## 일반적인 사용 사례
|
||||
|
||||
- 로깅 클래스
|
||||
- 데이터베이스에 대한 연결 관리
|
||||
- 파일 관리자
|
||||
|
||||
## 실제 사례
|
||||
|
||||
- [java.lang.Runtime#getRuntime()](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime%28%29)
|
||||
- [java.awt.Desktop#getDesktop()](http://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#getDesktop--)
|
||||
- [java.lang.System#getSecurityManager()](http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getSecurityManager--)
|
||||
|
||||
## 결과
|
||||
|
||||
- 자체 생성 및 수명주기를 제어하여 SRP (Single Responsibility Principle)를 위반합니다.
|
||||
- 이 개체가 사용하는 개체와 리소스가 할당 해제되는 것을 방지하는 전역 공유 인스턴스를 사용하도록 권장합니다.
|
||||
- 밀접하게 연결된 코드를 만듭니다. Singleton의 클라이언트는 테스트하기가 어려워집니다.
|
||||
- Singleton의 하위 클래스를 만드는 것이 거의 불가능합니다.
|
||||
|
||||
## 크레딧
|
||||
|
||||
- [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)
|
||||
- [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)
|
||||
- [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)
|
||||
- [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)
|
31
mutex/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Mutex
|
||||
folder: mutex
|
||||
permalink: /patterns/mutex/
|
||||
categories: Concurrency
|
||||
tags:
|
||||
- Decoupling
|
||||
---
|
||||
|
||||
## Also known as
|
||||
|
||||
* Mutual Exclusion Lock
|
||||
* Binary Semaphore
|
||||
|
||||
## Intent
|
||||
Create a lock which only allows a single thread to access a resource at any one instant.
|
||||
|
||||
## Class diagram
|
||||

|
||||
|
||||
## Applicability
|
||||
Use a Mutex when
|
||||
|
||||
* You need to prevent two threads accessing a critical section at the same time
|
||||
* Concurrent access to a resource could lead to a race condition
|
||||
|
||||
## Credits
|
||||
|
||||
* [Lock (computer science)](http://en.wikipedia.org/wiki/Lock_(computer_science))
|
||||
* [Semaphores](http://tutorials.jenkov.com/java-concurrency/semaphores.html)
|
BIN
mutex/etc/mutex.png
Normal file
After Width: | Height: | Size: 12 KiB |
27
mutex/etc/mutex.urm.puml
Normal file
@ -0,0 +1,27 @@
|
||||
@startuml
|
||||
package com.iluwatar.mutex {
|
||||
class App {
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class Jar {
|
||||
- beans : int
|
||||
- lock : Lock
|
||||
+ Jar(beans : int, lock : Lock)
|
||||
+ takeBean() : boolean
|
||||
}
|
||||
interface Lock {
|
||||
+ acquire() {abstract}
|
||||
+ release() {abstract}
|
||||
}
|
||||
class Mutex {
|
||||
- owner : Object
|
||||
+ Mutex()
|
||||
+ acquire()
|
||||
+ getOwner() : Object
|
||||
+ release()
|
||||
}
|
||||
}
|
||||
Jar --> "-lock" Lock
|
||||
Mutex ..|> Lock
|
||||
@enduml
|
61
mutex/pom.xml
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
|
||||
The MIT License
|
||||
Copyright © 2014-2019 Ilkka Seppälä
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
-->
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.24.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>mutex</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.iluwatar.mutex.App</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
49
mutex/src/main/java/com/iluwatar/mutex/App.java
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.mutex;
|
||||
|
||||
/**
|
||||
* A Mutex prevents multiple threads from accessing a resource simultaneously.
|
||||
*
|
||||
* <p>In this example we have two thieves who are taking beans from a jar. Only one thief can take
|
||||
* a bean at a time. This is ensured by a Mutex lock which must be acquired in order to access the
|
||||
* jar. Each thief attempts to acquire the lock, take a bean and then release the lock. If the lock
|
||||
* has already been acquired, the thief will be prevented from continuing (blocked) until the lock
|
||||
* has been released. The thieves stop taking beans once there are no beans left to take.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* main method.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
var mutex = new Mutex();
|
||||
var jar = new Jar(1000, mutex);
|
||||
var peter = new Thief("Peter", jar);
|
||||
var john = new Thief("John", jar);
|
||||
peter.start();
|
||||
john.start();
|
||||
}
|
||||
|
||||
}
|
@ -21,40 +21,47 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
package com.iluwatar.mutex;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MaintenanceLock {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MaintenanceLock.class);
|
||||
|
||||
private static MaintenanceLock instance;
|
||||
private boolean lock = true;
|
||||
/**
|
||||
* A Jar has a resource of beans which can only be accessed by a single Thief (thread) at any one
|
||||
* time. A Mutex lock is used to prevent more than one Thief taking a bean simultaneously.
|
||||
*/
|
||||
public class Jar {
|
||||
|
||||
/**
|
||||
* Get the instance of MaintenanceLock.
|
||||
*
|
||||
* @return singleton instance of MaintenanceLock
|
||||
* The lock which must be acquired to access the beans resource.
|
||||
*/
|
||||
public static MaintenanceLock getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (MaintenanceLock.class) {
|
||||
if (instance == null) {
|
||||
instance = new MaintenanceLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
private final Lock lock;
|
||||
|
||||
public boolean isLock() {
|
||||
return lock;
|
||||
}
|
||||
/**
|
||||
* The resource within the jar.
|
||||
*/
|
||||
private int beans;
|
||||
|
||||
public void setLock(boolean lock) {
|
||||
public Jar(int beans, Lock lock) {
|
||||
this.beans = beans;
|
||||
this.lock = lock;
|
||||
LOGGER.info("Maintenance lock is set to: " + lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for a thief to take a bean.
|
||||
*/
|
||||
public boolean takeBean() {
|
||||
var success = false;
|
||||
try {
|
||||
lock.acquire();
|
||||
success = beans > 0;
|
||||
if (success) {
|
||||
beans = beans - 1;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
lock.release();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
}
|
@ -21,9 +21,15 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
package com.iluwatar.mutex;
|
||||
|
||||
public interface ReceiptViewModel {
|
||||
/**
|
||||
* Lock is an interface for a lock which can be acquired and released.
|
||||
*/
|
||||
public interface Lock {
|
||||
|
||||
void acquire() throws InterruptedException;
|
||||
|
||||
void release();
|
||||
|
||||
void show();
|
||||
}
|
67
mutex/src/main/java/com/iluwatar/mutex/Mutex.java
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.mutex;
|
||||
|
||||
/**
|
||||
* Mutex is an implementation of a mutual exclusion lock.
|
||||
*/
|
||||
public class Mutex implements Lock {
|
||||
|
||||
/**
|
||||
* The current owner of the lock.
|
||||
*/
|
||||
private Object owner;
|
||||
|
||||
/**
|
||||
* Returns the current owner of the Mutex, or null if available.
|
||||
*/
|
||||
public Object getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called by a thread to acquire the lock. If the lock has already been acquired this will
|
||||
* wait until the lock has been released to re-attempt the acquire.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void acquire() throws InterruptedException {
|
||||
while (owner != null) {
|
||||
wait();
|
||||
}
|
||||
|
||||
owner = Thread.currentThread();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called by a thread to release the lock.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void release() {
|
||||
if (Thread.currentThread() == owner) {
|
||||
owner = null;
|
||||
notify();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -21,35 +21,47 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
package com.iluwatar.mutex;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class InsufficientFunds implements ReceiptViewModel {
|
||||
/**
|
||||
* Thief is a class which continually tries to acquire a jar and take a bean from it. When the jar
|
||||
* is empty the thief stops.
|
||||
*/
|
||||
public class Thief extends Thread {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(InsufficientFunds.class);
|
||||
|
||||
private String userName;
|
||||
private Double amount;
|
||||
private String itemName;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Thief.class);
|
||||
|
||||
/**
|
||||
* Constructor of InsufficientFunds.
|
||||
*
|
||||
* @param userName of the user
|
||||
* @param amount of the user's account
|
||||
* @param itemName of the item
|
||||
* The name of the thief.
|
||||
*/
|
||||
public InsufficientFunds(String userName, Double amount, String itemName) {
|
||||
this.userName = userName;
|
||||
this.amount = amount;
|
||||
this.itemName = itemName;
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The jar.
|
||||
*/
|
||||
private final Jar jar;
|
||||
|
||||
public Thief(String name, Jar jar) {
|
||||
this.name = name;
|
||||
this.jar = jar;
|
||||
}
|
||||
|
||||
/**
|
||||
* In the run method the thief repeatedly tries to take a bean until none are left.
|
||||
*/
|
||||
@Override
|
||||
public void show() {
|
||||
LOGGER.info("Insufficient funds: " + amount + " of user: " + userName
|
||||
+ " for buying item: " + itemName);
|
||||
public void run() {
|
||||
var beans = 0;
|
||||
|
||||
while (jar.takeBean()) {
|
||||
beans = beans + 1;
|
||||
LOGGER.info("{} took a bean.", name);
|
||||
}
|
||||
|
||||
LOGGER.info("{} took {} beans.", name, beans);
|
||||
}
|
||||
|
||||
}
|
@ -21,15 +21,19 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
package com.iluwatar.mutex;
|
||||
|
||||
public class MoneyTransaction {
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
private Double amount;
|
||||
private Double price;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
public MoneyTransaction(Double amount, Double price) {
|
||||
this.amount = amount;
|
||||
this.price = price;
|
||||
/**
|
||||
* Application Test Entrypoint
|
||||
*/
|
||||
class AppTest {
|
||||
|
||||
@Test
|
||||
void shouldExecuteApplicationWithoutException() {
|
||||
assertDoesNotThrow(() -> App.main(new String[]{}));
|
||||
}
|
||||
}
|
@ -21,23 +21,25 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
package com.iluwatar.mutex;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
public class InvalidUser implements ReceiptViewModel {
|
||||
import java.util.stream.IntStream;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(InvalidUser.class);
|
||||
/**
|
||||
* Test case for taking beans from a Jar
|
||||
*/
|
||||
public class JarTest {
|
||||
|
||||
private final String userName;
|
||||
|
||||
public InvalidUser(String userName) {
|
||||
this.userName = userName;
|
||||
@Test
|
||||
public void testTakeBeans() {
|
||||
var mutex = new Mutex();
|
||||
var jar = new Jar(10, mutex);
|
||||
IntStream.range(0, 10).mapToObj(i -> jar.takeBean()).forEach(Assertions::assertTrue);
|
||||
assertFalse(jar.takeBean());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
LOGGER.info("Invalid user: " + userName);
|
||||
}
|
||||
}
|
@ -21,25 +21,31 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
package com.iluwatar.mutex;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class OutOfStock implements ReceiptViewModel {
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(OutOfStock.class);
|
||||
/**
|
||||
* Test case for acquiring and releasing a Mutex
|
||||
*/
|
||||
public class MutexTest {
|
||||
|
||||
private String userName;
|
||||
private String itemName;
|
||||
|
||||
public OutOfStock(String userName, String itemName) {
|
||||
this.userName = userName;
|
||||
this.itemName = itemName;
|
||||
@Test
|
||||
public void acquireReleaseTest() {
|
||||
var mutex = new Mutex();
|
||||
assertNull(mutex.getOwner());
|
||||
try {
|
||||
mutex.acquire();
|
||||
assertEquals(mutex.getOwner(), Thread.currentThread());
|
||||
} catch (InterruptedException e) {
|
||||
fail(e.toString());
|
||||
}
|
||||
mutex.release();
|
||||
assertNull(mutex.getOwner());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
LOGGER.info("Out of stock: " + itemName + " for user = " + userName + " to buy");
|
||||
}
|
||||
}
|
||||
}
|
4
pom.xml
@ -141,6 +141,8 @@
|
||||
<module>module</module>
|
||||
<module>monad</module>
|
||||
<module>mute-idiom</module>
|
||||
<module>mutex</module>
|
||||
<module>semaphore</module>
|
||||
<module>hexagonal</module>
|
||||
<module>abstract-document</module>
|
||||
<module>aggregator-microservices</module>
|
||||
@ -197,7 +199,7 @@
|
||||
<module>filterer</module>
|
||||
<module>factory</module>
|
||||
<module>separated-interface</module>
|
||||
<module>special-case</module>
|
||||
<module>data-transfer-object-enum-impl</module>
|
||||
</modules>
|
||||
|
||||
<repositories>
|
||||
|
@ -1,28 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
The MIT License
|
||||
Copyright © 2014-2019 Ilkka Seppälä
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
@ -1,26 +1,3 @@
|
||||
/*
|
||||
* 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.registry;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
@ -1,26 +1,3 @@
|
||||
/*
|
||||
* 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.registry;
|
||||
|
||||
public class Customer {
|
||||
|
@ -1,26 +1,3 @@
|
||||
/*
|
||||
* 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.registry;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -1,26 +1,3 @@
|
||||
/*
|
||||
* 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.registry;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
33
semaphore/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Semaphore
|
||||
folder: semaphore
|
||||
permalink: /patterns/semaphore/
|
||||
categories: Concurrency
|
||||
tags:
|
||||
- Performance
|
||||
---
|
||||
|
||||
## Also known as
|
||||
Counting Semaphore
|
||||
|
||||
## Intent
|
||||
Create a lock which mediates access to a pool of resources.
|
||||
Only a limited number of threads, specified at the creation
|
||||
of the semaphore, can access the resources at any given time.
|
||||
A semaphore which only allows one concurrent access to a resource
|
||||
is called a binary semaphore.
|
||||
|
||||
## Class diagram
|
||||

|
||||
|
||||
## Applicability
|
||||
Use a Semaphore when
|
||||
|
||||
* You have a pool of resources to allocate to different threads
|
||||
* Concurrent access to a resource could lead to a race condition
|
||||
|
||||
## Credits
|
||||
|
||||
* [Semaphore(programming)] (http://en.wikipedia.org/wiki/Semaphore_(programming))
|
||||
* [Semaphores] (http://tutorials.jenkov.com/java-concurrency/semaphores.html)
|
BIN
semaphore/etc/semaphore.png
Normal file
After Width: | Height: | Size: 29 KiB |
56
semaphore/etc/semaphore.urm.puml
Normal file
@ -0,0 +1,56 @@
|
||||
@startuml
|
||||
package com.iluwatar.semaphore {
|
||||
class App {
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class Fruit {
|
||||
- type : FruitType
|
||||
+ Fruit(type : FruitType)
|
||||
+ getType() : FruitType
|
||||
+ toString() : String
|
||||
}
|
||||
enum FruitType {
|
||||
+ APPLE {static}
|
||||
+ LEMON {static}
|
||||
+ ORANGE {static}
|
||||
+ valueOf(name : String) : FruitType {static}
|
||||
+ values() : FruitType[] {static}
|
||||
}
|
||||
class FruitBowl {
|
||||
- fruit : List<Fruit>
|
||||
+ FruitBowl()
|
||||
+ countFruit() : int
|
||||
+ put(f : Fruit)
|
||||
+ take() : Fruit
|
||||
+ toString() : String
|
||||
}
|
||||
class FruitShop {
|
||||
- available : boolean[]
|
||||
- bowls : FruitBowl[]
|
||||
- semaphore : Semaphore
|
||||
+ FruitShop()
|
||||
+ countFruit() : int
|
||||
+ returnBowl(bowl : FruitBowl)
|
||||
+ takeBowl() : FruitBowl
|
||||
}
|
||||
interface Lock {
|
||||
+ acquire() {abstract}
|
||||
+ release() {abstract}
|
||||
}
|
||||
class Semaphore {
|
||||
- counter : int
|
||||
- licenses : int
|
||||
+ Semaphore(licenses : int)
|
||||
+ acquire()
|
||||
+ getAvailableLicenses() : int
|
||||
+ getNumLicenses() : int
|
||||
+ release()
|
||||
}
|
||||
}
|
||||
FruitType ..+ Fruit
|
||||
Fruit --> "-type" FruitType
|
||||
FruitShop --> "-semaphore" Semaphore
|
||||
FruitBowl --> "-fruit" Fruit
|
||||
Semaphore ..|> Lock
|
||||
@enduml
|
61
semaphore/pom.xml
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
|
||||
The MIT License
|
||||
Copyright © 2014-2019 Ilkka Seppälä
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
-->
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.24.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>semaphore</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.iluwatar.semaphore.App</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
50
semaphore/src/main/java/com/iluwatar/semaphore/App.java
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.semaphore;
|
||||
|
||||
/**
|
||||
* A Semaphore mediates access by a group of threads to a pool of resources.
|
||||
*
|
||||
* <p>In this example a group of customers are taking fruit from a fruit shop. There is a bowl each
|
||||
* of apples, oranges and lemons. Only one customer can access a bowl simultaneously. A Semaphore is
|
||||
* used to indicate how many resources are currently available and must be acquired in order for a
|
||||
* bowl to be given to a customer. Customers continually try to take fruit until there is no fruit
|
||||
* left in the shop.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* main method.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
var shop = new FruitShop();
|
||||
new Customer("Peter", shop).start();
|
||||
new Customer("Paul", shop).start();
|
||||
new Customer("Mary", shop).start();
|
||||
new Customer("John", shop).start();
|
||||
new Customer("Ringo", shop).start();
|
||||
new Customer("George", shop).start();
|
||||
}
|
||||
|
||||
}
|
@ -21,32 +21,62 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.strategy;
|
||||
package com.iluwatar.semaphore;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class LambdaStrategy {
|
||||
/**
|
||||
* A Customer attempts to repeatedly take Fruit from the FruitShop by taking Fruit from FruitBowl
|
||||
* instances.
|
||||
*/
|
||||
public class Customer extends Thread {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LambdaStrategy.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Customer.class);
|
||||
|
||||
public enum Strategy implements DragonSlayingStrategy {
|
||||
MeleeStrategy(() -> LOGGER.info(
|
||||
"With your Excalibur you severe the dragon's head!")),
|
||||
ProjectileStrategy(() -> LOGGER.info(
|
||||
"You shoot the dragon with the magical crossbow and it falls dead on the ground!")),
|
||||
SpellStrategy(() -> LOGGER.info(
|
||||
"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"));
|
||||
/**
|
||||
* Name of the Customer.
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
private final DragonSlayingStrategy dragonSlayingStrategy;
|
||||
/**
|
||||
* The FruitShop he is using.
|
||||
*/
|
||||
private final FruitShop fruitShop;
|
||||
|
||||
Strategy(DragonSlayingStrategy dragonSlayingStrategy) {
|
||||
this.dragonSlayingStrategy = dragonSlayingStrategy;
|
||||
}
|
||||
/**
|
||||
* Their bowl of Fruit.
|
||||
*/
|
||||
private final FruitBowl fruitBowl;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
dragonSlayingStrategy.execute();
|
||||
}
|
||||
/**
|
||||
* Customer constructor.
|
||||
*/
|
||||
public Customer(String name, FruitShop fruitShop) {
|
||||
this.name = name;
|
||||
this.fruitShop = fruitShop;
|
||||
this.fruitBowl = new FruitBowl();
|
||||
}
|
||||
|
||||
/**
|
||||
* The Customer repeatedly takes Fruit from the FruitShop until no Fruit remains.
|
||||
*/
|
||||
public void run() {
|
||||
|
||||
while (fruitShop.countFruit() > 0) {
|
||||
var bowl = fruitShop.takeBowl();
|
||||
if (bowl != null) {
|
||||
var fruit = bowl.take();
|
||||
if (fruit != null) {
|
||||
LOGGER.info("{} took an {}", name, fruit);
|
||||
fruitBowl.put(fruit);
|
||||
fruitShop.returnBowl(bowl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info("{} took {}", name, fruitBowl);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -21,21 +21,44 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
package com.iluwatar.semaphore;
|
||||
|
||||
public class ApplicationServicesImpl implements ApplicationServices {
|
||||
/**
|
||||
* Fruit is a resource stored in a FruitBowl.
|
||||
*/
|
||||
public class Fruit {
|
||||
|
||||
private DomainServicesImpl domain = new DomainServicesImpl();
|
||||
/**
|
||||
* Enumeration of Fruit Types.
|
||||
*/
|
||||
public enum FruitType {
|
||||
ORANGE, APPLE, LEMON
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReceiptViewModel loggedInUserPurchase(String userName, String itemName) {
|
||||
if (isDownForMaintenance()) {
|
||||
return new DownForMaintenance();
|
||||
private final FruitType type;
|
||||
|
||||
public Fruit(FruitType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public FruitType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* toString method.
|
||||
*/
|
||||
public String toString() {
|
||||
switch (type) {
|
||||
case ORANGE:
|
||||
return "Orange";
|
||||
case APPLE:
|
||||
return "Apple";
|
||||
case LEMON:
|
||||
return "Lemon";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
return this.domain.purchase(userName, itemName);
|
||||
}
|
||||
|
||||
private boolean isDownForMaintenance() {
|
||||
return MaintenanceLock.getInstance().isLock();
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.semaphore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A FruitBowl contains Fruit.
|
||||
*/
|
||||
public class FruitBowl {
|
||||
|
||||
private final List<Fruit> fruit = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Returns the amount of fruits left in bowl.
|
||||
*
|
||||
* @return The amount of Fruit left in the bowl.
|
||||
*/
|
||||
public int countFruit() {
|
||||
return fruit.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an item of Fruit into the bowl.
|
||||
*
|
||||
* @param f fruit
|
||||
*/
|
||||
public void put(Fruit f) {
|
||||
fruit.add(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take an item of Fruit out of the bowl.
|
||||
*
|
||||
* @return The Fruit taken out of the bowl, or null if empty.
|
||||
*/
|
||||
public Fruit take() {
|
||||
if (fruit.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return fruit.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* toString method.
|
||||
*/
|
||||
public String toString() {
|
||||
var apples = 0;
|
||||
var oranges = 0;
|
||||
var lemons = 0;
|
||||
|
||||
for (var f : fruit) {
|
||||
switch (f.getType()) {
|
||||
case APPLE:
|
||||
apples++;
|
||||
break;
|
||||
case ORANGE:
|
||||
oranges++;
|
||||
break;
|
||||
case LEMON:
|
||||
lemons++;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return apples + " Apples, " + oranges + " Oranges, and " + lemons + " Lemons";
|
||||
}
|
||||
}
|
120
semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.semaphore;
|
||||
|
||||
/**
|
||||
* A FruitShop contains three FruitBowl instances and controls access to them.
|
||||
*/
|
||||
public class FruitShop {
|
||||
|
||||
/**
|
||||
* The FruitBowl instances stored in the class.
|
||||
*/
|
||||
private final FruitBowl[] bowls = {
|
||||
new FruitBowl(),
|
||||
new FruitBowl(),
|
||||
new FruitBowl()
|
||||
};
|
||||
|
||||
/**
|
||||
* Access flags for each of the FruitBowl instances.
|
||||
*/
|
||||
private final boolean[] available = {
|
||||
true,
|
||||
true,
|
||||
true
|
||||
};
|
||||
|
||||
/**
|
||||
* The Semaphore that controls access to the class resources.
|
||||
*/
|
||||
private final Semaphore semaphore;
|
||||
|
||||
/**
|
||||
* FruitShop constructor.
|
||||
*/
|
||||
public FruitShop() {
|
||||
for (var i = 0; i < 100; i++) {
|
||||
bowls[0].put(new Fruit(Fruit.FruitType.APPLE));
|
||||
bowls[1].put(new Fruit(Fruit.FruitType.ORANGE));
|
||||
bowls[2].put(new Fruit(Fruit.FruitType.LEMON));
|
||||
}
|
||||
|
||||
semaphore = new Semaphore(3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of fruits left in shop.
|
||||
*
|
||||
* @return The amount of Fruit left in the shop.
|
||||
*/
|
||||
public synchronized int countFruit() {
|
||||
return bowls[0].countFruit() + bowls[1].countFruit() + bowls[2].countFruit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called by Customer to get a FruitBowl from the shop. This method will try to acquire the
|
||||
* Semaphore before returning the first available FruitBowl.
|
||||
*/
|
||||
public synchronized FruitBowl takeBowl() {
|
||||
|
||||
FruitBowl bowl = null;
|
||||
|
||||
try {
|
||||
semaphore.acquire();
|
||||
|
||||
if (available[0]) {
|
||||
bowl = bowls[0];
|
||||
available[0] = false;
|
||||
} else if (available[1]) {
|
||||
bowl = bowls[1];
|
||||
available[1] = false;
|
||||
} else if (available[2]) {
|
||||
bowl = bowls[2];
|
||||
available[2] = false;
|
||||
}
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
semaphore.release();
|
||||
}
|
||||
return bowl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called by a Customer instance to return a FruitBowl to the shop. This method releases
|
||||
* the Semaphore, making the FruitBowl available to another Customer.
|
||||
*/
|
||||
public synchronized void returnBowl(FruitBowl bowl) {
|
||||
if (bowl == bowls[0]) {
|
||||
available[0] = true;
|
||||
} else if (bowl == bowls[1]) {
|
||||
available[1] = true;
|
||||
} else if (bowl == bowls[2]) {
|
||||
available[2] = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -21,9 +21,15 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
package com.iluwatar.semaphore;
|
||||
|
||||
public interface ApplicationServices {
|
||||
/**
|
||||
* Lock is an interface for a lock which can be acquired and released.
|
||||
*/
|
||||
public interface Lock {
|
||||
|
||||
void acquire() throws InterruptedException;
|
||||
|
||||
void release();
|
||||
|
||||
ReceiptViewModel loggedInUserPurchase(String userName, String itemName);
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.semaphore;
|
||||
|
||||
/**
|
||||
* Semaphore is an implementation of a semaphore lock.
|
||||
*/
|
||||
public class Semaphore implements Lock {
|
||||
|
||||
private final int licenses;
|
||||
/**
|
||||
* The number of concurrent resource accesses which are allowed.
|
||||
*/
|
||||
private int counter;
|
||||
|
||||
public Semaphore(int licenses) {
|
||||
this.licenses = licenses;
|
||||
this.counter = licenses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of licenses managed by the Semaphore.
|
||||
*/
|
||||
public int getNumLicenses() {
|
||||
return licenses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of available licenses.
|
||||
*/
|
||||
public int getAvailableLicenses() {
|
||||
return counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called by a thread to acquire the lock. If there are no resources available this will
|
||||
* wait until the lock has been released to re-attempt the acquire.
|
||||
*/
|
||||
public synchronized void acquire() throws InterruptedException {
|
||||
while (counter == 0) {
|
||||
wait();
|
||||
}
|
||||
counter = counter - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called by a thread to release the lock.
|
||||
*/
|
||||
public synchronized void release() {
|
||||
if (counter < licenses) {
|
||||
counter = counter + 1;
|
||||
notify();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -21,16 +21,16 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
package com.iluwatar.semaphore;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
/**
|
||||
* Application test.
|
||||
* Application Test Entrypoint
|
||||
*/
|
||||
public class AppTest {
|
||||
class AppTest {
|
||||
|
||||
@Test
|
||||
void shouldExecuteWithoutException() {
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.semaphore;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test taking from and putting Fruit into a FruitBowl
|
||||
*/
|
||||
public class FruitBowlTest {
|
||||
|
||||
@Test
|
||||
public void fruitBowlTest() {
|
||||
var fbowl = new FruitBowl();
|
||||
|
||||
assertEquals(0, fbowl.countFruit());
|
||||
|
||||
for (var i = 1; i <= 10; i++) {
|
||||
fbowl.put(new Fruit(Fruit.FruitType.LEMON));
|
||||
assertEquals(i, fbowl.countFruit());
|
||||
}
|
||||
|
||||
for (var i = 9; i >= 0; i--) {
|
||||
assertNotNull(fbowl.take());
|
||||
assertEquals(i, fbowl.countFruit());
|
||||
}
|
||||
|
||||
assertNull(fbowl.take());
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.semaphore;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for acquiring and releasing a Semaphore
|
||||
*/
|
||||
public class SemaphoreTest {
|
||||
|
||||
@Test
|
||||
public void acquireReleaseTest() {
|
||||
var sphore = new Semaphore(3);
|
||||
|
||||
assertEquals(3, sphore.getAvailableLicenses());
|
||||
|
||||
for (var i = 2; i >= 0; i--) {
|
||||
try {
|
||||
sphore.acquire();
|
||||
assertEquals(i, sphore.getAvailableLicenses());
|
||||
} catch (InterruptedException e) {
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 1; i <= 3; i++) {
|
||||
sphore.release();
|
||||
assertEquals(i, sphore.getAvailableLicenses());
|
||||
}
|
||||
|
||||
sphore.release();
|
||||
assertEquals(3, sphore.getAvailableLicenses());
|
||||
}
|
||||
}
|
@ -1,368 +0,0 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Special Case
|
||||
folder: special-case
|
||||
permalink: /patterns/special-case/
|
||||
categories: Behavioral
|
||||
tags:
|
||||
- Extensibility
|
||||
---
|
||||
|
||||
## Intent
|
||||
|
||||
Define some special cases, and encapsulates them into subclasses that provide different special behaviors.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
|
||||
> In an e-commerce system, presentation layer expects application layer to produce certain view model.
|
||||
> We have a successful scenario, in which receipt view model contains actual data from the purchase,
|
||||
> and a couple of failure scenarios.
|
||||
|
||||
In plain words
|
||||
|
||||
> Special Case pattern allows returning non-null real objects that perform special behaviors.
|
||||
|
||||
In [Patterns of Enterprise Application Architecture](https://martinfowler.com/books/eaa.html) says
|
||||
the difference from Null Object Pattern
|
||||
|
||||
> If you’ll pardon the unresistable pun, I see Null Object as special case of Special Case.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
To focus on the pattern itself, we implement DB and maintenance lock of the e-commerce system by the singleton instance.
|
||||
|
||||
```java
|
||||
public class Db {
|
||||
private static Db instance;
|
||||
private Map<String, User> userName2User;
|
||||
private Map<User, Account> user2Account;
|
||||
private Map<String, Product> itemName2Product;
|
||||
|
||||
public static Db getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (Db.class) {
|
||||
if (instance == null) {
|
||||
instance = new Db();
|
||||
instance.userName2User = new HashMap<>();
|
||||
instance.user2Account = new HashMap<>();
|
||||
instance.itemName2Product = new HashMap<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void seedUser(String userName, Double amount) {
|
||||
User user = new User(userName);
|
||||
instance.userName2User.put(userName, user);
|
||||
Account account = new Account(amount);
|
||||
instance.user2Account.put(user, account);
|
||||
}
|
||||
|
||||
public void seedItem(String itemName, Double price) {
|
||||
Product item = new Product(price);
|
||||
itemName2Product.put(itemName, item);
|
||||
}
|
||||
|
||||
public User findUserByUserName(String userName) {
|
||||
if (!userName2User.containsKey(userName)) {
|
||||
return null;
|
||||
}
|
||||
return userName2User.get(userName);
|
||||
}
|
||||
|
||||
public Account findAccountByUser(User user) {
|
||||
if (!user2Account.containsKey(user)) {
|
||||
return null;
|
||||
}
|
||||
return user2Account.get(user);
|
||||
}
|
||||
|
||||
public Product findProductByItemName(String itemName) {
|
||||
if (!itemName2Product.containsKey(itemName)) {
|
||||
return null;
|
||||
}
|
||||
return itemName2Product.get(itemName);
|
||||
}
|
||||
|
||||
public class User {
|
||||
private String userName;
|
||||
|
||||
public User(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public ReceiptDto purchase(Product item) {
|
||||
return new ReceiptDto(item.getPrice());
|
||||
}
|
||||
}
|
||||
|
||||
public class Account {
|
||||
private Double amount;
|
||||
|
||||
public Account(Double amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public MoneyTransaction withdraw(Double price) {
|
||||
if (price > amount) {
|
||||
return null;
|
||||
}
|
||||
return new MoneyTransaction(amount, price);
|
||||
}
|
||||
|
||||
public Double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
|
||||
public class Product {
|
||||
private Double price;
|
||||
|
||||
public Product(Double price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public Double getPrice() {
|
||||
return price;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MaintenanceLock {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MaintenanceLock.class);
|
||||
|
||||
private static MaintenanceLock instance;
|
||||
private boolean lock = true;
|
||||
|
||||
public static MaintenanceLock getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (MaintenanceLock.class) {
|
||||
if (instance == null) {
|
||||
instance = new MaintenanceLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public boolean isLock() {
|
||||
return lock;
|
||||
}
|
||||
|
||||
public void setLock(boolean lock) {
|
||||
this.lock = lock;
|
||||
LOGGER.info("Maintenance lock is set to: " + lock);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Let's first introduce presentation layer, the receipt view model interface and its implementation of successful scenario.
|
||||
|
||||
```java
|
||||
public interface ReceiptViewModel {
|
||||
void show();
|
||||
}
|
||||
|
||||
public class ReceiptDto implements ReceiptViewModel {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ReceiptDto.class);
|
||||
|
||||
private Double price;
|
||||
|
||||
public ReceiptDto(Double price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public Double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
LOGGER.info("Receipt: " + price + " paid");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And here are the implementations of failure scenarios, which are the special cases.
|
||||
|
||||
```java
|
||||
public class DownForMaintenance implements ReceiptViewModel {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DownForMaintenance.class);
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
LOGGER.info("Down for maintenance");
|
||||
}
|
||||
}
|
||||
|
||||
public class InvalidUser implements ReceiptViewModel {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(InvalidUser.class);
|
||||
|
||||
private final String userName;
|
||||
|
||||
public InvalidUser(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
LOGGER.info("Invalid user: " + userName);
|
||||
}
|
||||
}
|
||||
|
||||
public class OutOfStock implements ReceiptViewModel {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(OutOfStock.class);
|
||||
|
||||
private String userName;
|
||||
private String itemName;
|
||||
|
||||
public OutOfStock(String userName, String itemName) {
|
||||
this.userName = userName;
|
||||
this.itemName = itemName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
LOGGER.info("Out of stock: " + itemName + " for user = " + userName + " to buy");
|
||||
}
|
||||
}
|
||||
|
||||
public class InsufficientFunds implements ReceiptViewModel {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(InsufficientFunds.class);
|
||||
|
||||
private String userName;
|
||||
private Double amount;
|
||||
private String itemName;
|
||||
|
||||
public InsufficientFunds(String userName, Double amount, String itemName) {
|
||||
this.userName = userName;
|
||||
this.amount = amount;
|
||||
this.itemName = itemName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
LOGGER.info("Insufficient funds: " + amount + " of user: " + userName
|
||||
+ " for buying item: " + itemName);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Second, here's the application layer, the application services implementation and the domain services implementation.
|
||||
|
||||
```java
|
||||
public class ApplicationServicesImpl implements ApplicationServices {
|
||||
private DomainServicesImpl domain = new DomainServicesImpl();
|
||||
|
||||
@Override
|
||||
public ReceiptViewModel loggedInUserPurchase(String userName, String itemName) {
|
||||
if (isDownForMaintenance()) {
|
||||
return new DownForMaintenance();
|
||||
}
|
||||
return this.domain.purchase(userName, itemName);
|
||||
}
|
||||
|
||||
private boolean isDownForMaintenance() {
|
||||
return MaintenanceLock.getInstance().isLock();
|
||||
}
|
||||
}
|
||||
|
||||
public class DomainServicesImpl implements DomainServices {
|
||||
public ReceiptViewModel purchase(String userName, String itemName) {
|
||||
Db.User user = Db.getInstance().findUserByUserName(userName);
|
||||
if (user == null) {
|
||||
return new InvalidUser(userName);
|
||||
}
|
||||
|
||||
Db.Account account = Db.getInstance().findAccountByUser(user);
|
||||
return purchase(user, account, itemName);
|
||||
}
|
||||
|
||||
private ReceiptViewModel purchase(Db.User user, Db.Account account, String itemName) {
|
||||
Db.Product item = Db.getInstance().findProductByItemName(itemName);
|
||||
if (item == null) {
|
||||
return new OutOfStock(user.getUserName(), itemName);
|
||||
}
|
||||
|
||||
ReceiptDto receipt = user.purchase(item);
|
||||
MoneyTransaction transaction = account.withdraw(receipt.getPrice());
|
||||
if (transaction == null) {
|
||||
return new InsufficientFunds(user.getUserName(), account.getAmount(), itemName);
|
||||
}
|
||||
|
||||
return receipt;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Finally, the client send requests the application services to get the presentation view.
|
||||
|
||||
```java
|
||||
// DB seeding
|
||||
LOGGER.info("Db seeding: " + "1 user: {\"ignite1771\", amount = 1000.0}, "
|
||||
+ "2 products: {\"computer\": price = 800.0, \"car\": price = 20000.0}");
|
||||
Db.getInstance().seedUser("ignite1771", 1000.0);
|
||||
Db.getInstance().seedItem("computer", 800.0);
|
||||
Db.getInstance().seedItem("car", 20000.0);
|
||||
|
||||
var applicationServices = new ApplicationServicesImpl();
|
||||
ReceiptViewModel receipt;
|
||||
|
||||
LOGGER.info("[REQUEST] User: " + "abc123" + " buy product: " + "tv");
|
||||
receipt = applicationServices.loggedInUserPurchase("abc123", "tv");
|
||||
receipt.show();
|
||||
MaintenanceLock.getInstance().setLock(false);
|
||||
LOGGER.info("[REQUEST] User: " + "abc123" + " buy product: " + "tv");
|
||||
receipt = applicationServices.loggedInUserPurchase("abc123", "tv");
|
||||
receipt.show();
|
||||
LOGGER.info("[REQUEST] User: " + "ignite1771" + " buy product: " + "tv");
|
||||
receipt = applicationServices.loggedInUserPurchase("ignite1771", "tv");
|
||||
receipt.show();
|
||||
LOGGER.info("[REQUEST] User: " + "ignite1771" + " buy product: " + "car");
|
||||
receipt = applicationServices.loggedInUserPurchase("ignite1771", "car");
|
||||
receipt.show();
|
||||
LOGGER.info("[REQUEST] User: " + "ignite1771" + " buy product: " + "computer");
|
||||
receipt = applicationServices.loggedInUserPurchase("ignite1771", "computer");
|
||||
receipt.show();
|
||||
```
|
||||
|
||||
Program output of every request:
|
||||
|
||||
```
|
||||
Down for maintenance
|
||||
Invalid user: abc123
|
||||
Out of stock: tv for user = ignite1771 to buy
|
||||
Insufficient funds: 1000.0 of user: ignite1771 for buying item: car
|
||||
Receipt: 800.0 paid
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Special Case pattern when
|
||||
|
||||
* You have multiple places in the system that have the same behavior after a conditional check
|
||||
for a particular class instance, or the same behavior after a null check.
|
||||
* Return a real object that performs the real behavior, instead of a null object that performs nothing.
|
||||
|
||||
## Tutorial
|
||||
|
||||
* [Special Case Tutorial](https://www.codinghelmet.com/articles/reduce-cyclomatic-complexity-special-case)
|
||||
|
||||
## Credits
|
||||
|
||||
* [How to Reduce Cyclomatic Complexity Part 2: Special Case Pattern](https://www.codinghelmet.com/articles/reduce-cyclomatic-complexity-special-case)
|
||||
* [Patterns of Enterprise Application Architecture](https://martinfowler.com/books/eaa.html)
|
||||
* [Special Case](https://www.martinfowler.com/eaaCatalog/specialCase.html)
|
@ -1,119 +0,0 @@
|
||||
@startuml
|
||||
left to right direction
|
||||
package com.iluwatar.specialcase {
|
||||
class App {
|
||||
- LOGGER : Logger {static}
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
interface ApplicationServices {
|
||||
+ loggedInUserPurchase(String, String) : ReceiptViewModel {abstract}
|
||||
}
|
||||
class ApplicationServicesImpl {
|
||||
- domain : DomainServicesImpl
|
||||
+ ApplicationServicesImpl()
|
||||
- isDownForMaintenance() : boolean
|
||||
+ loggedInUserPurchase(userName : String, itemName : String) : ReceiptViewModel
|
||||
}
|
||||
class Db {
|
||||
- instance : Db {static}
|
||||
- itemName2Product : Map<String, Product>
|
||||
- user2Account : Map<User, Account>
|
||||
- userName2User : Map<String, User>
|
||||
+ Db()
|
||||
+ findAccountByUser(user : User) : Account
|
||||
+ findProductByItemName(itemName : String) : Product
|
||||
+ findUserByUserName(userName : String) : User
|
||||
+ getInstance() : Db {static}
|
||||
+ seedItem(itemName : String, price : Double)
|
||||
+ seedUser(userName : String, amount : Double)
|
||||
}
|
||||
class Account {
|
||||
- amount : Double
|
||||
+ Account(this$0 : Double)
|
||||
+ getAmount() : Double
|
||||
+ withdraw(price : Double) : MoneyTransaction
|
||||
}
|
||||
class Product {
|
||||
- price : Double
|
||||
+ Product(this$0 : Double)
|
||||
+ getPrice() : Double
|
||||
}
|
||||
class User {
|
||||
- userName : String
|
||||
+ User(this$0 : String)
|
||||
+ getUserName() : String
|
||||
+ purchase(item : Product) : ReceiptDto
|
||||
}
|
||||
interface DomainServices {
|
||||
}
|
||||
class DomainServicesImpl {
|
||||
+ DomainServicesImpl()
|
||||
- purchase(user : User, account : Account, itemName : String) : ReceiptViewModel
|
||||
+ purchase(userName : String, itemName : String) : ReceiptViewModel
|
||||
}
|
||||
class DownForMaintenance {
|
||||
- LOGGER : Logger {static}
|
||||
+ DownForMaintenance()
|
||||
+ show()
|
||||
}
|
||||
class InsufficientFunds {
|
||||
- LOGGER : Logger {static}
|
||||
- amount : Double
|
||||
- itemName : String
|
||||
- userName : String
|
||||
+ InsufficientFunds(userName : String, amount : Double, itemName : String)
|
||||
+ show()
|
||||
}
|
||||
class InvalidUser {
|
||||
- LOGGER : Logger {static}
|
||||
- userName : String
|
||||
+ InvalidUser(userName : String)
|
||||
+ show()
|
||||
}
|
||||
class MaintenanceLock {
|
||||
- LOGGER : Logger {static}
|
||||
- instance : MaintenanceLock {static}
|
||||
- lock : boolean
|
||||
+ MaintenanceLock()
|
||||
+ getInstance() : MaintenanceLock {static}
|
||||
+ isLock() : boolean
|
||||
+ setLock(lock : boolean)
|
||||
}
|
||||
class MoneyTransaction {
|
||||
- amount : Double
|
||||
- price : Double
|
||||
+ MoneyTransaction(amount : Double, price : Double)
|
||||
}
|
||||
class OutOfStock {
|
||||
- LOGGER : Logger {static}
|
||||
- itemName : String
|
||||
- userName : String
|
||||
+ OutOfStock(userName : String, itemName : String)
|
||||
+ show()
|
||||
}
|
||||
class ReceiptDto {
|
||||
- LOGGER : Logger {static}
|
||||
- price : Double
|
||||
+ ReceiptDto(price : Double)
|
||||
+ getPrice() : Double
|
||||
+ show()
|
||||
}
|
||||
interface ReceiptViewModel {
|
||||
+ show() {abstract}
|
||||
}
|
||||
}
|
||||
User --+ Db
|
||||
Product --+ Db
|
||||
MaintenanceLock --> "-instance" MaintenanceLock
|
||||
Db --> "-instance" Db
|
||||
ApplicationServicesImpl --> "-domain" DomainServicesImpl
|
||||
Account --+ Db
|
||||
ApplicationServicesImpl ..|> ApplicationServices
|
||||
DomainServicesImpl ..|> DomainServices
|
||||
DownForMaintenance ..|> ReceiptViewModel
|
||||
InsufficientFunds ..|> ReceiptViewModel
|
||||
InvalidUser ..|> ReceiptViewModel
|
||||
OutOfStock ..|> ReceiptViewModel
|
||||
ReceiptDto ..|> ReceiptViewModel
|
||||
@enduml
|
Before Width: | Height: | Size: 448 KiB |
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>The Special Case Pattern is a software design pattern that encapsulates particular cases
|
||||
* into subclasses that provide special behaviors.</p>
|
||||
*
|
||||
* <p>In this example ({@link ReceiptViewModel}) encapsulates all particular cases.</p>
|
||||
*/
|
||||
public class App {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
||||
|
||||
/**
|
||||
* Program entry point.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// DB seeding
|
||||
LOGGER.info("Db seeding: " + "1 user: {\"ignite1771\", amount = 1000.0}, "
|
||||
+ "2 products: {\"computer\": price = 800.0, \"car\": price = 20000.0}");
|
||||
Db.getInstance().seedUser("ignite1771", 1000.0);
|
||||
Db.getInstance().seedItem("computer", 800.0);
|
||||
Db.getInstance().seedItem("car", 20000.0);
|
||||
|
||||
final var applicationServices = new ApplicationServicesImpl();
|
||||
ReceiptViewModel receipt;
|
||||
|
||||
LOGGER.info("[REQUEST] User: " + "abc123" + " buy product: " + "tv");
|
||||
receipt = applicationServices.loggedInUserPurchase("abc123", "tv");
|
||||
receipt.show();
|
||||
MaintenanceLock.getInstance().setLock(false);
|
||||
LOGGER.info("[REQUEST] User: " + "abc123" + " buy product: " + "tv");
|
||||
receipt = applicationServices.loggedInUserPurchase("abc123", "tv");
|
||||
receipt.show();
|
||||
LOGGER.info("[REQUEST] User: " + "ignite1771" + " buy product: " + "tv");
|
||||
receipt = applicationServices.loggedInUserPurchase("ignite1771", "tv");
|
||||
receipt.show();
|
||||
LOGGER.info("[REQUEST] User: " + "ignite1771" + " buy product: " + "car");
|
||||
receipt = applicationServices.loggedInUserPurchase("ignite1771", "car");
|
||||
receipt.show();
|
||||
LOGGER.info("[REQUEST] User: " + "ignite1771" + " buy product: " + "computer");
|
||||
receipt = applicationServices.loggedInUserPurchase("ignite1771", "computer");
|
||||
receipt.show();
|
||||
}
|
||||
}
|
@ -1,173 +0,0 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Db {
|
||||
|
||||
private static Db instance;
|
||||
private Map<String, User> userName2User;
|
||||
private Map<User, Account> user2Account;
|
||||
private Map<String, Product> itemName2Product;
|
||||
|
||||
/**
|
||||
* Get the instance of Db.
|
||||
*
|
||||
* @return singleton instance of Db class
|
||||
*/
|
||||
public static Db getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (Db.class) {
|
||||
if (instance == null) {
|
||||
instance = new Db();
|
||||
instance.userName2User = new HashMap<>();
|
||||
instance.user2Account = new HashMap<>();
|
||||
instance.itemName2Product = new HashMap<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed a user into Db.
|
||||
*
|
||||
* @param userName of the user
|
||||
* @param amount of the user's account
|
||||
*/
|
||||
public void seedUser(String userName, Double amount) {
|
||||
User user = new User(userName);
|
||||
instance.userName2User.put(userName, user);
|
||||
Account account = new Account(amount);
|
||||
instance.user2Account.put(user, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed an item into Db.
|
||||
*
|
||||
* @param itemName of the item
|
||||
* @param price of the item
|
||||
*/
|
||||
public void seedItem(String itemName, Double price) {
|
||||
Product item = new Product(price);
|
||||
itemName2Product.put(itemName, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a user with the userName.
|
||||
*
|
||||
* @param userName of the user
|
||||
* @return instance of User
|
||||
*/
|
||||
public User findUserByUserName(String userName) {
|
||||
if (!userName2User.containsKey(userName)) {
|
||||
return null;
|
||||
}
|
||||
return userName2User.get(userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an account of the user.
|
||||
*
|
||||
* @param user in Db
|
||||
* @return instance of Account of the user
|
||||
*/
|
||||
public Account findAccountByUser(User user) {
|
||||
if (!user2Account.containsKey(user)) {
|
||||
return null;
|
||||
}
|
||||
return user2Account.get(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a product with the itemName.
|
||||
*
|
||||
* @param itemName of the item
|
||||
* @return instance of Product
|
||||
*/
|
||||
public Product findProductByItemName(String itemName) {
|
||||
if (!itemName2Product.containsKey(itemName)) {
|
||||
return null;
|
||||
}
|
||||
return itemName2Product.get(itemName);
|
||||
}
|
||||
|
||||
public class User {
|
||||
|
||||
private String userName;
|
||||
|
||||
public User(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public ReceiptDto purchase(Product item) {
|
||||
return new ReceiptDto(item.getPrice());
|
||||
}
|
||||
}
|
||||
|
||||
public class Account {
|
||||
|
||||
private Double amount;
|
||||
|
||||
public Account(Double amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Withdraw the price of the item from the account.
|
||||
*
|
||||
* @param price of the item
|
||||
* @return instance of MoneyTransaction
|
||||
*/
|
||||
public MoneyTransaction withdraw(Double price) {
|
||||
if (price > amount) {
|
||||
return null;
|
||||
}
|
||||
return new MoneyTransaction(amount, price);
|
||||
}
|
||||
|
||||
public Double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
|
||||
public class Product {
|
||||
|
||||
private Double price;
|
||||
|
||||
public Product(Double price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public Double getPrice() {
|
||||
return price;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
|
||||
public interface DomainServices {
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
|
||||
public class DomainServicesImpl implements DomainServices {
|
||||
|
||||
/**
|
||||
* Domain purchase with userName and itemName, with validation for userName.
|
||||
*
|
||||
* @param userName of the user
|
||||
* @param itemName of the item
|
||||
* @return instance of ReceiptViewModel
|
||||
*/
|
||||
public ReceiptViewModel purchase(String userName, String itemName) {
|
||||
Db.User user = Db.getInstance().findUserByUserName(userName);
|
||||
if (user == null) {
|
||||
return new InvalidUser(userName);
|
||||
}
|
||||
|
||||
Db.Account account = Db.getInstance().findAccountByUser(user);
|
||||
return purchase(user, account, itemName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Domain purchase with user, account and itemName,
|
||||
* with validation for whether product is out of stock
|
||||
* and whether user has insufficient funds in the account.
|
||||
*
|
||||
* @param user in Db
|
||||
* @param account in Db
|
||||
* @param itemName of the item
|
||||
* @return instance of ReceiptViewModel
|
||||
*/
|
||||
private ReceiptViewModel purchase(Db.User user, Db.Account account, String itemName) {
|
||||
Db.Product item = Db.getInstance().findProductByItemName(itemName);
|
||||
if (item == null) {
|
||||
return new OutOfStock(user.getUserName(), itemName);
|
||||
}
|
||||
|
||||
ReceiptDto receipt = user.purchase(item);
|
||||
MoneyTransaction transaction = account.withdraw(receipt.getPrice());
|
||||
if (transaction == null) {
|
||||
return new InsufficientFunds(user.getUserName(), account.getAmount(), itemName);
|
||||
}
|
||||
|
||||
return receipt;
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class DownForMaintenance implements ReceiptViewModel {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DownForMaintenance.class);
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
LOGGER.info("Down for maintenance");
|
||||
}
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specialcase;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ch.qos.logback.classic.Level;
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.read.ListAppender;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
/**
|
||||
* Special cases unit tests. (including the successful scenario {@link ReceiptDto})
|
||||
*/
|
||||
public class SpecialCasesTest {
|
||||
private static ApplicationServices applicationServices;
|
||||
private static ReceiptViewModel receipt;
|
||||
|
||||
@BeforeAll
|
||||
static void beforeAll() {
|
||||
Db.getInstance().seedUser("ignite1771", 1000.0);
|
||||
Db.getInstance().seedItem("computer", 800.0);
|
||||
Db.getInstance().seedItem("car", 20000.0);
|
||||
|
||||
applicationServices = new ApplicationServicesImpl();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void beforeEach() {
|
||||
MaintenanceLock.getInstance().setLock(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDownForMaintenance() {
|
||||
final Logger LOGGER = (Logger) LoggerFactory.getLogger(DownForMaintenance.class);
|
||||
|
||||
ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
|
||||
listAppender.start();
|
||||
LOGGER.addAppender(listAppender);
|
||||
|
||||
MaintenanceLock.getInstance().setLock(true);
|
||||
receipt = applicationServices.loggedInUserPurchase(null, null);
|
||||
receipt.show();
|
||||
|
||||
List<ILoggingEvent> loggingEventList = listAppender.list;
|
||||
assertEquals("Down for maintenance", loggingEventList.get(0).getMessage());
|
||||
assertEquals(Level.INFO, loggingEventList.get(0).getLevel());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidUser() {
|
||||
final Logger LOGGER = (Logger) LoggerFactory.getLogger(InvalidUser.class);
|
||||
|
||||
ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
|
||||
listAppender.start();
|
||||
LOGGER.addAppender(listAppender);
|
||||
|
||||
receipt = applicationServices.loggedInUserPurchase("a", null);
|
||||
receipt.show();
|
||||
|
||||
List<ILoggingEvent> loggingEventList = listAppender.list;
|
||||
assertEquals("Invalid user: a", loggingEventList.get(0).getMessage());
|
||||
assertEquals(Level.INFO, loggingEventList.get(0).getLevel());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutOfStock() {
|
||||
final Logger LOGGER = (Logger) LoggerFactory.getLogger(OutOfStock.class);
|
||||
|
||||
ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
|
||||
listAppender.start();
|
||||
LOGGER.addAppender(listAppender);
|
||||
|
||||
receipt = applicationServices.loggedInUserPurchase("ignite1771", "tv");
|
||||
receipt.show();
|
||||
|
||||
List<ILoggingEvent> loggingEventList = listAppender.list;
|
||||
assertEquals("Out of stock: tv for user = ignite1771 to buy"
|
||||
, loggingEventList.get(0).getMessage());
|
||||
assertEquals(Level.INFO, loggingEventList.get(0).getLevel());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsufficientFunds() {
|
||||
final Logger LOGGER = (Logger) LoggerFactory.getLogger(InsufficientFunds.class);
|
||||
|
||||
ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
|
||||
listAppender.start();
|
||||
LOGGER.addAppender(listAppender);
|
||||
|
||||
receipt = applicationServices.loggedInUserPurchase("ignite1771", "car");
|
||||
receipt.show();
|
||||
|
||||
List<ILoggingEvent> loggingEventList = listAppender.list;
|
||||
assertEquals("Insufficient funds: 1000.0 of user: ignite1771 for buying item: car"
|
||||
, loggingEventList.get(0).getMessage());
|
||||
assertEquals(Level.INFO, loggingEventList.get(0).getLevel());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReceiptDto() {
|
||||
final Logger LOGGER = (Logger) LoggerFactory.getLogger(ReceiptDto.class);
|
||||
|
||||
ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
|
||||
listAppender.start();
|
||||
LOGGER.addAppender(listAppender);
|
||||
|
||||
receipt = applicationServices.loggedInUserPurchase("ignite1771", "computer");
|
||||
receipt.show();
|
||||
|
||||
List<ILoggingEvent> loggingEventList = listAppender.list;
|
||||
assertEquals("Receipt: 800.0 paid"
|
||||
, loggingEventList.get(0).getMessage());
|
||||
assertEquals(Level.INFO, loggingEventList.get(0).getLevel());
|
||||
}
|
||||
}
|
@ -122,51 +122,6 @@ Program output:
|
||||
You cast the spell of disintegration and the dragon vaporizes in a pile of dust!
|
||||
```
|
||||
|
||||
What's more, the new feature Lambda Expressions in Java 8 provides another approach for the implementation:
|
||||
|
||||
```java
|
||||
public class LambdaStrategy {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LambdaStrategy.class);
|
||||
|
||||
public enum Strategy implements DragonSlayingStrategy {
|
||||
MeleeStrategy(() -> LOGGER.info(
|
||||
"With your Excalibur you severe the dragon's head!")),
|
||||
ProjectileStrategy(() -> LOGGER.info(
|
||||
"You shoot the dragon with the magical crossbow and it falls dead on the ground!")),
|
||||
SpellStrategy(() -> LOGGER.info(
|
||||
"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"));
|
||||
|
||||
private final DragonSlayingStrategy dragonSlayingStrategy;
|
||||
|
||||
Strategy(DragonSlayingStrategy dragonSlayingStrategy) {
|
||||
this.dragonSlayingStrategy = dragonSlayingStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
dragonSlayingStrategy.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And here's the dragonslayer in action.
|
||||
|
||||
```java
|
||||
LOGGER.info("Green dragon spotted ahead!");
|
||||
dragonSlayer.changeStrategy(LambdaStrategy.Strategy.MeleeStrategy);
|
||||
dragonSlayer.goToBattle();
|
||||
LOGGER.info("Red dragon emerges.");
|
||||
dragonSlayer.changeStrategy(LambdaStrategy.Strategy.ProjectileStrategy);
|
||||
dragonSlayer.goToBattle();
|
||||
LOGGER.info("Black dragon lands before you.");
|
||||
dragonSlayer.changeStrategy(LambdaStrategy.Strategy.SpellStrategy);
|
||||
dragonSlayer.goToBattle();
|
||||
```
|
||||
|
||||
Program output is the same as above one.
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||
|
@ -14,19 +14,6 @@ package com.iluwatar.strategy {
|
||||
interface DragonSlayingStrategy {
|
||||
+ execute() {abstract}
|
||||
}
|
||||
class LambdaStrategy {
|
||||
- LOGGER : Logger {static}
|
||||
+ LambdaStrategy()
|
||||
}
|
||||
enum Strategy {
|
||||
+ MeleeStrategy {static}
|
||||
+ ProjectileStrategy {static}
|
||||
+ SpellStrategy {static}
|
||||
- dragonSlayingStrategy : DragonSlayingStrategy
|
||||
+ execute()
|
||||
+ valueOf(name : String) : Strategy {static}
|
||||
+ values() : Strategy[] {static}
|
||||
}
|
||||
class MeleeStrategy {
|
||||
- LOGGER : Logger {static}
|
||||
+ MeleeStrategy()
|
||||
@ -43,10 +30,7 @@ package com.iluwatar.strategy {
|
||||
+ execute()
|
||||
}
|
||||
}
|
||||
Strategy ..+ LambdaStrategy
|
||||
Strategy --> "-dragonSlayingStrategy" DragonSlayingStrategy
|
||||
DragonSlayer --> "-strategy" DragonSlayingStrategy
|
||||
Strategy ..|> DragonSlayingStrategy
|
||||
MeleeStrategy ..|> DragonSlayingStrategy
|
||||
ProjectileStrategy ..|> DragonSlayingStrategy
|
||||
SpellStrategy ..|> DragonSlayingStrategy
|
||||
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 29 KiB |
@ -45,7 +45,7 @@ public class App {
|
||||
|
||||
/**
|
||||
* Program entry point.
|
||||
*
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
@ -60,7 +60,7 @@ public class App {
|
||||
dragonSlayer.changeStrategy(new SpellStrategy());
|
||||
dragonSlayer.goToBattle();
|
||||
|
||||
// Java 8 functional implementation Strategy pattern
|
||||
// Java 8 Strategy pattern
|
||||
LOGGER.info("Green dragon spotted ahead!");
|
||||
dragonSlayer = new DragonSlayer(
|
||||
() -> LOGGER.info("With your Excalibur you severe the dragon's head!"));
|
||||
@ -73,16 +73,5 @@ public class App {
|
||||
dragonSlayer.changeStrategy(() -> LOGGER.info(
|
||||
"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"));
|
||||
dragonSlayer.goToBattle();
|
||||
|
||||
// Java 8 lambda implementation with enum Strategy pattern
|
||||
LOGGER.info("Green dragon spotted ahead!");
|
||||
dragonSlayer.changeStrategy(LambdaStrategy.Strategy.MeleeStrategy);
|
||||
dragonSlayer.goToBattle();
|
||||
LOGGER.info("Red dragon emerges.");
|
||||
dragonSlayer.changeStrategy(LambdaStrategy.Strategy.ProjectileStrategy);
|
||||
dragonSlayer.goToBattle();
|
||||
LOGGER.info("Black dragon lands before you.");
|
||||
dragonSlayer.changeStrategy(LambdaStrategy.Strategy.SpellStrategy);
|
||||
dragonSlayer.goToBattle();
|
||||
}
|
||||
}
|
||||
|
42
tr/README.md
@ -1,42 +0,0 @@
|
||||
<!-- Biçimlendirme nedeniyle bu satır boş bırakılmalıdır böylelikle hoş bir görüntüye sahip olabiliriz. örneğin web sitesi -->
|
||||
|
||||

|
||||
[](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)
|
||||
[](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
|
||||
[](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
|
||||
[](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
# Giriş
|
||||
|
||||
Tasarım desenleri, bir yazılım mühendisi bir uygulamayı veya sistemi tasarlarken yaygın sorunları çözmek için kullanabileceği en iyi çözüm prensipleridir.
|
||||
|
||||
Tasarım desenleri, test edilip kanıtlanmış prensipler olduğu için yazılım geliştirme sürecini hızlandırabilir.
|
||||
|
||||
Tasarım desenlerini yeniden kullanmak, büyük sorunlara neden olan ince sorunları önlemeye yardımcı olur ve aynı zamanda tasarım desenlerine alışkın olan yazılım mühendisileri ve yazılım mimarları için kod okunabilirliğini artırır.
|
||||
|
||||
# Başlangıç
|
||||
|
||||
Bu site Java Tasarım Desenlerini sergiliyor. Çözümler, açık kaynak topluluğundan deneyimli yazılım mühendisileri ve yazılım mimarları tarafından geliştirilmiştir. Bu yazılım desenleri, detaylı açıklamalarıyla veya kaynak kodlarına bakılarak göz atılabilir. Kaynak kod örneklerinde iyi derecede açıklayıcı yorum satırlarına sahip olup ve belirli bir tasarım deseninin nasıl uygulanacağına dair programlama dersi olarak düşünülebilir. Savaşta en çok kanıtlanmış açık kaynak Java teknolojilerini kullanıyoruz.
|
||||
|
||||
Bu projeye başlamadan önce çeşitli [Yazılım Tasarım İlkelerine](https://java-design-patterns.com/principles/) aşina olmalısınız.
|
||||
|
||||
Tüm tasarımlar olabildiğince basit olmalıdır. [KISS](https://en.wikipedia.org/wiki/KISS_principle), [YAGNI](https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it) ve [Do The Simplest Thing That Could Possibly Work](https://learning.oreilly.com/library/view/extreme-programming-pocket/9781449399849/ch17.html) ilkeleri ile başlamalısınız.
|
||||
|
||||
Bu kavramlara aşina olduktan sonra, aşağıdaki yaklaşımlardan herhangi birini kullanarak [mevcut tasarım desenlerini](https://java-design-patterns.com/patterns/) derinlemesine incelemeye başlayabilirsiniz.
|
||||
|
||||
- İsme göre belirli bir tasarım deseni arayın. Bulamadınız mı? Lütfen yeni bir tasarım deseni için [bizim ile](https://github.com/iluwatar/java-design-patterns/issues) iletişime geçin.
|
||||
- Performance, Gang of Four ya da Data access gibi etiketleri kullanın.
|
||||
- Creational(Yaratıcı Tasarım Desenleri), Behavioral(Davranışsal Tasarım Desenleri), ve Structural(Yapısal Tasarım Desenleri) gibi tasarım kategorilerini kullanın.
|
||||
|
||||
Umarım bu sitede sunulan nesne yönelimli çözümleri yazılım mimarileriniz için yararlı bulursunuz ve onları geliştirirken bizim kadar eğlenirsiniz.
|
||||
|
||||
# Nasıl Katkı Sağlayabilirim
|
||||
|
||||
Projeye katkıda bulunmaya istekliysen, ilgili bilgileri [geliştirici wiki'mizde](https://github.com/iluwatar/java-design-patterns/wiki) bulabilirsin. [Gitter](https://gitter.im/iluwatar/java-design-patterns) ile size yardımcı olacağız ve sorularınızı cevaplayacağız.
|
||||
|
||||
# Lisans
|
||||
|
||||
Bu proje, MIT lisansı koşulları altında lisanslanmıştır.
|