From f6d43975fae9bc256217fc3d40a452bd736108d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sat, 5 Jun 2021 10:33:25 +0300 Subject: [PATCH 01/11] docs: Grammatical fixes for Abstract Factory (#1782) * Grammatical fixes * Update abstract-factory/README.md Co-authored-by: Subhrodip Mohanta --- abstract-factory/README.md | 32 +++++++++---------- .../com/iluwatar/abstractfactory/App.java | 6 ++-- .../com/iluwatar/abstractfactory/ElfArmy.java | 2 +- .../iluwatar/abstractfactory/ElfCastle.java | 2 +- .../com/iluwatar/abstractfactory/ElfKing.java | 2 +- .../com/iluwatar/abstractfactory/OrcArmy.java | 2 +- .../iluwatar/abstractfactory/OrcCastle.java | 2 +- .../com/iluwatar/abstractfactory/OrcKing.java | 2 +- .../abstractfactory/AbstractFactoryTest.java | 12 +++---- .../com/iluwatar/abstractfactory/AppTest.java | 5 +-- 10 files changed, 32 insertions(+), 35 deletions(-) diff --git a/abstract-factory/README.md b/abstract-factory/README.md index cc95c382c..0321f7454 100644 --- a/abstract-factory/README.md +++ b/abstract-factory/README.md @@ -20,9 +20,9 @@ objects without specifying their concrete classes. ## Explanation -Real world example +Real-world example -> To create a kingdom we need objects with a common theme. Elven kingdom needs an Elven king, Elven castle and Elven army whereas Orcish kingdom needs an Orcish king, Orcish castle and Orcish army. There is a dependency between the objects in the kingdom. +> To create a kingdom we need objects with a common theme. The elven kingdom needs an elven king, elven castle, and elven army whereas the orcish kingdom needs an orcish king, orcish castle, and orcish army. There is a dependency between the objects in the kingdom. In plain words @@ -34,7 +34,7 @@ Wikipedia says **Programmatic Example** -Translating the kingdom example above. First of all we have some interfaces and implementation for the objects in the +Translating the kingdom example above. First of all, we have some interfaces and implementation for the objects in the kingdom. ```java @@ -52,21 +52,21 @@ public interface Army { // Elven implementations -> public class ElfCastle implements Castle { - static final String DESCRIPTION = "This is the Elven castle!"; + static final String DESCRIPTION = "This is the elven castle!"; @Override public String getDescription() { return DESCRIPTION; } } public class ElfKing implements King { - static final String DESCRIPTION = "This is the Elven king!"; + static final String DESCRIPTION = "This is the elven king!"; @Override public String getDescription() { return DESCRIPTION; } } public class ElfArmy implements Army { - static final String DESCRIPTION = "This is the Elven Army!"; + static final String DESCRIPTION = "This is the elven Army!"; @Override public String getDescription() { return DESCRIPTION; @@ -77,7 +77,7 @@ public class ElfArmy implements Army { ``` -Then we have the abstraction and implementations for the kingdom factory +Then we have the abstraction and implementations for the kingdom factory. ```java public interface KingdomFactory { @@ -111,7 +111,7 @@ public class OrcKingdomFactory implements KingdomFactory { } ``` -Now we have our abstract factory that lets us make family of related objects i.e. Elven kingdom factory creates Elven castle, king and army etc. +Now we have the abstract factory that lets us make a family of related objects i.e. elven kingdom factory creates elven castle, king and army, etc. ```java var factory = new ElfKingdomFactory(); @@ -127,13 +127,13 @@ army.getDescription(); Program output: ```java -This is the Elven castle! -This is the Elven king! -This is the Elven Army! +This is the elven castle! +This is the elven king! +This is the elven Army! ``` -Now, we can design a factory for our different kingdom factories. In this example, we created FactoryMaker, responsible for returning an instance of either ElfKingdomFactory or OrcKingdomFactory. -The client can use FactoryMaker to create the desired concrete factory which, in turn, will produce different concrete objects (Army, King, Castle). +Now, we can design a factory for our different kingdom factories. In this example, we created `FactoryMaker`, responsible for returning an instance of either `ElfKingdomFactory` or `OrcKingdomFactory`. +The client can use `FactoryMaker` to create the desired concrete factory which, in turn, will produce different concrete objects (derived from `Army`, `King`, `Castle`). In this example, we also used an enum to parameterize which type of kingdom factory the client will ask for. ```java @@ -179,8 +179,8 @@ public static void main(String[] args) { Use the Abstract Factory pattern when -* The system should be independent of how its products are created, composed and represented -* The system should be configured with one of multiple families of products +* The system should be independent of how its products are created, composed, and represented +* The system should be configured with one of the multiple families of products * The family of related product objects is designed to be used together, and you need to enforce this constraint * You want to provide a class library of products, and you want to reveal just their interfaces, not their implementations * The lifetime of the dependency is conceptually shorter than the lifetime of the consumer. @@ -200,7 +200,7 @@ Example use cases * Dependency injection in java hides the service class dependencies that can lead to runtime errors that would have been caught at compile time. * While the pattern is great when creating predefined objects, adding the new ones might be challenging. -* The code becomes more complicated than it should be, since a lot of new interfaces and classes are introduced along with the pattern. +* The code becomes more complicated than it should be since a lot of new interfaces and classes are introduced along with the pattern. ## Tutorial diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java index d208002a7..a5a3c74d7 100644 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java +++ b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java @@ -37,7 +37,7 @@ import lombok.extern.slf4j.Slf4j; * *

The essence of the Abstract Factory pattern is a factory interface ({@link KingdomFactory}) * and its implementations ( {@link ElfKingdomFactory}, {@link OrcKingdomFactory}). The example uses - * both concrete implementations to create a king, a castle and an army. + * both concrete implementations to create a king, a castle, and an army. */ @Slf4j public class App implements Runnable { @@ -60,13 +60,13 @@ public class App implements Runnable { @Override public void run() { - LOGGER.info("Elf Kingdom"); + LOGGER.info("elf kingdom"); createKingdom(Kingdom.FactoryMaker.KingdomType.ELF); LOGGER.info(kingdom.getArmy().getDescription()); LOGGER.info(kingdom.getCastle().getDescription()); LOGGER.info(kingdom.getKing().getDescription()); - LOGGER.info("Orc Kingdom"); + LOGGER.info("orc kingdom"); createKingdom(Kingdom.FactoryMaker.KingdomType.ORC); LOGGER.info(kingdom.getArmy().getDescription()); LOGGER.info(kingdom.getCastle().getDescription()); diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfArmy.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfArmy.java index ad54943aa..91a2393ec 100644 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfArmy.java +++ b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfArmy.java @@ -28,7 +28,7 @@ package com.iluwatar.abstractfactory; */ public class ElfArmy implements Army { - static final String DESCRIPTION = "This is the Elven Army!"; + static final String DESCRIPTION = "This is the elven army!"; @Override public String getDescription() { diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfCastle.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfCastle.java index 9c2ca1d4b..80fadc5cb 100644 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfCastle.java +++ b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfCastle.java @@ -28,7 +28,7 @@ package com.iluwatar.abstractfactory; */ public class ElfCastle implements Castle { - static final String DESCRIPTION = "This is the Elven castle!"; + static final String DESCRIPTION = "This is the elven castle!"; @Override public String getDescription() { diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKing.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKing.java index aa64a489f..843e057ea 100644 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKing.java +++ b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKing.java @@ -28,7 +28,7 @@ package com.iluwatar.abstractfactory; */ public class ElfKing implements King { - static final String DESCRIPTION = "This is the Elven king!"; + static final String DESCRIPTION = "This is the elven king!"; @Override public String getDescription() { diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcArmy.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcArmy.java index fa7bf3889..61f04c9d2 100644 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcArmy.java +++ b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcArmy.java @@ -28,7 +28,7 @@ package com.iluwatar.abstractfactory; */ public class OrcArmy implements Army { - static final String DESCRIPTION = "This is the Orc Army!"; + static final String DESCRIPTION = "This is the orc army!"; @Override public String getDescription() { diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcCastle.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcCastle.java index fea7c1866..f394e0a09 100644 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcCastle.java +++ b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcCastle.java @@ -28,7 +28,7 @@ package com.iluwatar.abstractfactory; */ public class OrcCastle implements Castle { - static final String DESCRIPTION = "This is the Orc castle!"; + static final String DESCRIPTION = "This is the orc castle!"; @Override public String getDescription() { diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKing.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKing.java index 9a47a9d0b..fcc59d4b7 100644 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKing.java +++ b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKing.java @@ -28,7 +28,7 @@ package com.iluwatar.abstractfactory; */ public class OrcKing implements King { - static final String DESCRIPTION = "This is the Orc king!"; + static final String DESCRIPTION = "This is the orc king!"; @Override public String getDescription() { diff --git a/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java b/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java index 3136ee29f..c77b61d29 100644 --- a/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java +++ b/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java @@ -29,14 +29,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; /** - * Test for abstract factory. + * Tests for abstract factory. */ class AbstractFactoryTest { private final App app = new App(); @Test - void king() { + void verifyKingCreation() { app.createKingdom(Kingdom.FactoryMaker.KingdomType.ELF); final var kingdom = app.getKingdom(); @@ -51,7 +51,7 @@ class AbstractFactoryTest { } @Test - void castle() { + void verifyCastleCreation() { app.createKingdom(Kingdom.FactoryMaker.KingdomType.ELF); final var kingdom = app.getKingdom(); @@ -66,7 +66,7 @@ class AbstractFactoryTest { } @Test - void army() { + void verifyArmyCreation() { app.createKingdom(Kingdom.FactoryMaker.KingdomType.ELF); final var kingdom = app.getKingdom(); @@ -81,7 +81,7 @@ class AbstractFactoryTest { } @Test - void createElfKingdom() { + void verifyElfKingdomCreation() { app.createKingdom(Kingdom.FactoryMaker.KingdomType.ELF); final var kingdom = app.getKingdom(); @@ -97,7 +97,7 @@ class AbstractFactoryTest { } @Test - void createOrcKingdom() { + void verifyOrcKingdomCreation() { app.createKingdom(Kingdom.FactoryMaker.KingdomType.ORC); final var kingdom = app.getKingdom(); diff --git a/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AppTest.java b/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AppTest.java index c5589895d..5a6e433b8 100644 --- a/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AppTest.java +++ b/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AppTest.java @@ -28,10 +28,7 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; /** - * Issue: Add at least one assertion to this test case. - * - * Solution: Inserted assertion to check whether the execution of the main method in {@link App} - * throws an exception. + * Check whether the execution of the main method in {@link App} throws an exception. */ class AppTest { From 43e7ca515ae73815a26c41c63a45db58fd19f00e Mon Sep 17 00:00:00 2001 From: Samuel Souza Date: Mon, 7 Jun 2021 14:00:44 -0300 Subject: [PATCH 02/11] refactor: #1012 - Resolve Sonar report: missing assertions in several AppTest classes (#1784) Co-authored-by: Subhrodip Mohanta --- .../src/test/java/com/iluwatar/filterer/AppTest.java | 5 ++++- monad/src/test/java/com/iluwatar/monad/AppTest.java | 9 ++++++--- .../src/test/java/com/iluwatar/monostate/AppTest.java | 9 ++++++--- .../src/test/java/com/iluwatar/multiton/AppTest.java | 11 +++++++---- .../test/java/com/iluwatar/object/pool/AppTest.java | 4 +++- .../java/com/iluwatar/parameter/object/AppTest.java | 9 +++------ .../saga/orchestration/SagaApplicationTest.java | 8 +++++--- 7 files changed, 34 insertions(+), 21 deletions(-) diff --git a/filterer/src/test/java/com/iluwatar/filterer/AppTest.java b/filterer/src/test/java/com/iluwatar/filterer/AppTest.java index 9ba98dd23..92e7d57e9 100644 --- a/filterer/src/test/java/com/iluwatar/filterer/AppTest.java +++ b/filterer/src/test/java/com/iluwatar/filterer/AppTest.java @@ -23,11 +23,14 @@ package com.iluwatar.filterer; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + import org.junit.jupiter.api.Test; class AppTest { + @Test void shouldLaunchApp() { - App.main(new String[]{}); + assertDoesNotThrow(() -> App.main(new String[]{})); } } \ No newline at end of file diff --git a/monad/src/test/java/com/iluwatar/monad/AppTest.java b/monad/src/test/java/com/iluwatar/monad/AppTest.java index f7ecc6d50..bb3f5422a 100644 --- a/monad/src/test/java/com/iluwatar/monad/AppTest.java +++ b/monad/src/test/java/com/iluwatar/monad/AppTest.java @@ -23,16 +23,19 @@ package com.iluwatar.monad; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + import org.junit.jupiter.api.Test; /** * Application Test */ -public class AppTest { + +class AppTest { @Test - void testMain() { - App.main(new String[]{}); + void shouldExecuteApplicationWithoutException() { + assertDoesNotThrow(() -> App.main(new String[]{})); } } diff --git a/monostate/src/test/java/com/iluwatar/monostate/AppTest.java b/monostate/src/test/java/com/iluwatar/monostate/AppTest.java index f03b7fa5a..79dd1d4e4 100644 --- a/monostate/src/test/java/com/iluwatar/monostate/AppTest.java +++ b/monostate/src/test/java/com/iluwatar/monostate/AppTest.java @@ -23,16 +23,19 @@ package com.iluwatar.monostate; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + import org.junit.jupiter.api.Test; /** * Application Test Entry */ -public class AppTest { + +class AppTest { @Test - void testMain() { - App.main(new String[]{}); + void shouldExecuteApplicationWithoutException() { + assertDoesNotThrow(() -> App.main(new String[]{})); } } diff --git a/multiton/src/test/java/com/iluwatar/multiton/AppTest.java b/multiton/src/test/java/com/iluwatar/multiton/AppTest.java index 0a092dcf3..c9cc9a49d 100644 --- a/multiton/src/test/java/com/iluwatar/multiton/AppTest.java +++ b/multiton/src/test/java/com/iluwatar/multiton/AppTest.java @@ -23,15 +23,18 @@ package com.iluwatar.multiton; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + import org.junit.jupiter.api.Test; /** - * Application test + * Test if the application starts without throwing an exception. */ -public class AppTest { + +class AppTest { @Test - void test() { - App.main(new String[]{}); + void shouldExecuteApplicationWithoutException() { + assertDoesNotThrow(() -> App.main(new String[]{})); } } diff --git a/object-pool/src/test/java/com/iluwatar/object/pool/AppTest.java b/object-pool/src/test/java/com/iluwatar/object/pool/AppTest.java index 202a162c8..b51bf7acd 100644 --- a/object-pool/src/test/java/com/iluwatar/object/pool/AppTest.java +++ b/object-pool/src/test/java/com/iluwatar/object/pool/AppTest.java @@ -23,6 +23,8 @@ package com.iluwatar.object.pool; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + import org.junit.jupiter.api.Test; /** @@ -34,6 +36,6 @@ class AppTest { @Test void shouldExecuteApplicationWithoutException() { - App.main(new String[]{}); + assertDoesNotThrow(() -> App.main(new String[]{})); } } diff --git a/parameter-object/src/test/java/com/iluwatar/parameter/object/AppTest.java b/parameter-object/src/test/java/com/iluwatar/parameter/object/AppTest.java index 16baef96f..9fa2cb93a 100644 --- a/parameter-object/src/test/java/com/iluwatar/parameter/object/AppTest.java +++ b/parameter-object/src/test/java/com/iluwatar/parameter/object/AppTest.java @@ -23,19 +23,16 @@ package com.iluwatar.parameter.object; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Application test */ class AppTest { - private static final Logger LOGGER = LoggerFactory.getLogger(AppTest.class); - @Test void shouldExecuteApplicationWithoutException() { - App.main(new String[]{}); - LOGGER.info("Executed successfully without exception."); + assertDoesNotThrow(() -> App.main(new String[]{})); } } diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java index 29a2f7eb6..d3f102828 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java @@ -23,15 +23,17 @@ package com.iluwatar.saga.orchestration; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + import org.junit.jupiter.api.Test; /** - * empty test + * Test if the application starts without throwing an exception. */ class SagaApplicationTest { @Test - void mainTest() { - SagaApplication.main(new String[]{}); + void shouldExecuteApplicationWithoutException() { + assertDoesNotThrow(() -> SagaApplication.main(new String[]{})); } } From eade10a98d6d3e38a17254980ca27cb72ff40103 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Mon, 7 Jun 2021 22:32:23 +0530 Subject: [PATCH 03/11] docs: add samuelpsouza as a contributor (#1785) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: Subhrodip Mohanta Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 5ee720dbd..798cd6a90 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1541,6 +1541,15 @@ "contributions": [ "code" ] + }, + { + "login": "samuelpsouza", + "name": "Samuel Souza", + "avatar_url": "https://avatars.githubusercontent.com/u/17254162?v=4", + "profile": "https://www.linkedin.com/in/souzasamuel/", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 4, diff --git a/README.md b/README.md index bd02e894d..eacced422 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns) [![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![All Contributors](https://img.shields.io/badge/all_contributors-169-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-170-orange.svg?style=flat-square)](#contributors-)
@@ -329,6 +329,7 @@ This project is licensed under the terms of the MIT license.
Xenilo137

💻 +
Samuel Souza

💻 From bbdff14a66c1f8d6f407461f092d8740fff5732f Mon Sep 17 00:00:00 2001 From: jinishavora <40777762+jinishavora@users.noreply.github.com> Date: Tue, 8 Jun 2021 14:40:24 -0400 Subject: [PATCH 04/11] Fix: Fixing License issue in MVVM pattern (#1701) * Fixing License issue in MVVM pattern * Updating LICENSE.md * Updating pom.xml * License header update to MVVM module only. * Updating pom and removing gpl txt * Adding gpl txt file Co-authored-by: Jinisha --- LICENSE.md | 5 +- gpl-3.0.txt | 674 ++++++++++++++++++ lgpl-3.0.txt | 165 +++++ model-view-viewmodel/pom.xml | 14 +- .../src/main/assembly/webapp.xml | 15 +- .../iluwatar/model/view/viewmodel/Book.java | 14 +- .../model/view/viewmodel/BookService.java | 16 +- .../model/view/viewmodel/BookServiceImpl.java | 14 +- .../model/view/viewmodel/BookViewModel.java | 14 +- .../src/main/webapp/WEB-INF/web.xml | 14 +- .../model/view/viewmodel/BookTest.java | 14 +- pom.xml | 14 +- 12 files changed, 926 insertions(+), 47 deletions(-) create mode 100644 gpl-3.0.txt create mode 100644 lgpl-3.0.txt diff --git a/LICENSE.md b/LICENSE.md index ff341fcb6..b239e7987 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2021 Ilkka Seppälä +Copyright 2014-2021 Ilkka Seppl Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,3 +19,6 @@ 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. + +Module Model-view-viewmodel is using ZK framework +ZK framework is licensed under LGPL and the license can be found at lgpl-3.0.txt diff --git a/gpl-3.0.txt b/gpl-3.0.txt new file mode 100644 index 000000000..e72bfddab --- /dev/null +++ b/gpl-3.0.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/lgpl-3.0.txt b/lgpl-3.0.txt new file mode 100644 index 000000000..0a041280b --- /dev/null +++ b/lgpl-3.0.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/model-view-viewmodel/pom.xml b/model-view-viewmodel/pom.xml index 77fa3340d..e14bb9f69 100644 --- a/model-view-viewmodel/pom.xml +++ b/model-view-viewmodel/pom.xml @@ -1,7 +1,7 @@ + - diff --git a/model-view-viewmodel/src/test/java/com/iluwatar/model/view/viewmodel/BookTest.java b/model-view-viewmodel/src/test/java/com/iluwatar/model/view/viewmodel/BookTest.java index 40a4d89d0..bd1c57609 100644 --- a/model-view-viewmodel/src/test/java/com/iluwatar/model/view/viewmodel/BookTest.java +++ b/model-view-viewmodel/src/test/java/com/iluwatar/model/view/viewmodel/BookTest.java @@ -1,5 +1,6 @@ /* - * The MIT License + * The MIT License (MIT) + * * Copyright © 2014-2021 Ilkka Seppälä * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -9,16 +10,19 @@ * 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 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. + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Module Model-view-viewmodel is using ZK framework + * ZK framework is licensed under LGPL and the license can be found at lgpl-3.0.txt */ package com.iluwatar.model.view.viewmodel; diff --git a/pom.xml b/pom.xml index 8173972bd..df2f45317 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,8 @@ Date: Thu, 24 Jun 2021 15:57:20 +0300 Subject: [PATCH 05/11] task: Explanations and grammar fixes for all the GoF patterns (#1791) * Grammatical fixes to command pattern * Update bridge pattern readme * Fixes to builder pattern grammar * Update chain of responsibility * Improvements to the composite example * Fixes to headings * Minor updates to decorator pattern * Update facade * Update factory example * Update factory method * Update flyweight * Interpreter explanation * Update iterator readme * Add explanation for mediator pattern * Grammatical fixes to memento * Grammar fixes for observer * Update explanation for the prototype pattern * Proxy pattern grammar fixes * Update singleton * Grammar fixes to state pattern * Grammar fixes for strategy * Grammar fixes, template method * Grammar fixes for visitor * Fix typo --- abstract-factory/README.md | 4 +- adapter/README.md | 4 +- bridge/README.md | 35 ++-- builder/README.md | 8 +- {chain => chain-of-responsibility}/README.md | 35 ++-- .../etc/chain-of-responsibility.urm.png | Bin .../etc/chain-of-responsibility.urm.puml | 0 {chain => chain-of-responsibility}/pom.xml | 2 +- .../src/main/java/com/iluwatar/chain/App.java | 0 .../java/com/iluwatar/chain/OrcCommander.java | 0 .../main/java/com/iluwatar/chain/OrcKing.java | 0 .../java/com/iluwatar/chain/OrcOfficer.java | 0 .../java/com/iluwatar/chain/OrcSoldier.java | 0 .../main/java/com/iluwatar/chain/Request.java | 0 .../com/iluwatar/chain/RequestHandler.java | 0 .../java/com/iluwatar/chain/RequestType.java | 0 .../test/java/com/iluwatar/chain/AppTest.java | 0 .../java/com/iluwatar/chain/OrcKingTest.java | 0 command/README.md | 29 ++- .../main/java/com/iluwatar/command/App.java | 2 +- composite/README.md | 30 ++- .../main/java/com/iluwatar/composite/App.java | 13 +- .../java/com/iluwatar/composite/Sentence.java | 2 +- decorator/README.md | 32 +-- .../main/java/com/iluwatar/decorator/App.java | 4 +- facade/README.md | 2 +- factory-method/README.md | 30 ++- .../java/com/iluwatar/factory/method/App.java | 39 ++-- .../factory/method/ElfBlacksmith.java | 4 + .../iluwatar/factory/method/ElfWeapon.java | 2 +- .../factory/method/OrcBlacksmith.java | 5 + .../iluwatar/factory/method/OrcWeapon.java | 2 +- factory/README.md | 82 ++++---- factory/etc/factory.urm.png | Bin 25438 -> 29351 bytes factory/etc/factory.urm.puml | 33 ++-- .../main/java/com/iluwatar/factory/App.java | 13 +- .../iluwatar/factory/{Car.java => Coin.java} | 4 +- .../{CarsFactory.java => CoinFactory.java} | 8 +- .../factory/{CarType.java => CoinType.java} | 11 +- .../factory/{Ferrari.java => CopperCoin.java} | 6 +- .../factory/{Ford.java => GoldCoin.java} | 6 +- ...sFactoryTest.java => CoinFactoryTest.java} | 9 +- flyweight/README.md | 100 +++++++--- .../com/iluwatar/flyweight/AlchemistShop.java | 8 +- .../main/java/com/iluwatar/flyweight/App.java | 4 +- interpreter/README.md | 157 ++++++++++++++- .../java/com/iluwatar/interpreter/App.java | 36 +++- iterator/README.md | 8 +- mediator/README.md | 185 +++++++++++++++++- memento/README.md | 10 +- observer/README.md | 12 +- .../main/java/com/iluwatar/observer/App.java | 2 +- pom.xml | 2 +- prototype/README.md | 140 ++++++++++--- .../main/java/com/iluwatar/prototype/App.java | 2 +- proxy/README.md | 4 +- singleton/README.md | 27 ++- .../main/java/com/iluwatar/singleton/App.java | 16 +- state/README.md | 8 +- .../src/main/java/com/iluwatar/state/App.java | 2 +- .../main/java/com/iluwatar/state/State.java | 1 - strategy/README.md | 22 +-- .../main/java/com/iluwatar/strategy/App.java | 2 +- template-method/README.md | 15 +- visitor/README.md | 6 +- .../main/java/com/iluwatar/visitor/App.java | 4 +- 66 files changed, 872 insertions(+), 357 deletions(-) rename {chain => chain-of-responsibility}/README.md (86%) rename chain/etc/chain.urm.png => chain-of-responsibility/etc/chain-of-responsibility.urm.png (100%) rename chain/etc/chain.urm.puml => chain-of-responsibility/etc/chain-of-responsibility.urm.puml (100%) rename {chain => chain-of-responsibility}/pom.xml (97%) rename {chain => chain-of-responsibility}/src/main/java/com/iluwatar/chain/App.java (100%) rename {chain => chain-of-responsibility}/src/main/java/com/iluwatar/chain/OrcCommander.java (100%) rename {chain => chain-of-responsibility}/src/main/java/com/iluwatar/chain/OrcKing.java (100%) rename {chain => chain-of-responsibility}/src/main/java/com/iluwatar/chain/OrcOfficer.java (100%) rename {chain => chain-of-responsibility}/src/main/java/com/iluwatar/chain/OrcSoldier.java (100%) rename {chain => chain-of-responsibility}/src/main/java/com/iluwatar/chain/Request.java (100%) rename {chain => chain-of-responsibility}/src/main/java/com/iluwatar/chain/RequestHandler.java (100%) rename {chain => chain-of-responsibility}/src/main/java/com/iluwatar/chain/RequestType.java (100%) rename {chain => chain-of-responsibility}/src/test/java/com/iluwatar/chain/AppTest.java (100%) rename {chain => chain-of-responsibility}/src/test/java/com/iluwatar/chain/OrcKingTest.java (100%) rename factory/src/main/java/com/iluwatar/factory/{Car.java => Coin.java} (96%) rename factory/src/main/java/com/iluwatar/factory/{CarsFactory.java => CoinFactory.java} (87%) rename factory/src/main/java/com/iluwatar/factory/{CarType.java => CoinType.java} (89%) rename factory/src/main/java/com/iluwatar/factory/{Ferrari.java => CopperCoin.java} (90%) rename factory/src/main/java/com/iluwatar/factory/{Ford.java => GoldCoin.java} (90%) rename factory/src/test/java/com/iluwatar/factory/{CarsFactoryTest.java => CoinFactoryTest.java} (88%) diff --git a/abstract-factory/README.md b/abstract-factory/README.md index 0321f7454..71073b32b 100644 --- a/abstract-factory/README.md +++ b/abstract-factory/README.md @@ -196,13 +196,13 @@ Example use cases * Unit test case writing becomes much easier * UI tools for different OS -## Consequences: +## Consequences * Dependency injection in java hides the service class dependencies that can lead to runtime errors that would have been caught at compile time. * While the pattern is great when creating predefined objects, adding the new ones might be challenging. * The code becomes more complicated than it should be since a lot of new interfaces and classes are introduced along with the pattern. -## Tutorial +## Tutorials * [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java) diff --git a/adapter/README.md b/adapter/README.md index eca6ea8d0..f1f818492 100644 --- a/adapter/README.md +++ b/adapter/README.md @@ -105,7 +105,7 @@ Use the Adapter pattern when * you need to use several existing subclasses, but it's impractical to adapt their interface by subclassing every one. An object adapter can adapt the interface of its parent class. * most of the applications using third party libraries use adapters as a middle layer between the application and the 3rd party library to decouple the application from the library. If another library has to be used only an adapter for the new library is required without having to change the application code. -## Consequences: +## Consequences Class and object adapters have different trade-offs. A class adapter * adapts Adaptee to Target by committing to a concrete Adaptee class. As a consequence, a class adapter won’t work when we want to adapt a class and all its subclasses. @@ -118,7 +118,7 @@ An object adapter * makes it harder to override Adaptee behavior. It will require subclassing Adaptee and making Adapter refer to the subclass rather than the Adaptee itself. -## Real world examples +## Known uses * [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-) diff --git a/bridge/README.md b/bridge/README.md index 6dfad9ab9..1c5ccb8ae 100644 --- a/bridge/README.md +++ b/bridge/README.md @@ -19,7 +19,7 @@ Decouple an abstraction from its implementation so that the two can vary indepen ## Explanation -Real world example +Real-world example > Consider you have a weapon with different enchantments, and you are supposed to allow mixing > different weapons with different enchantments. What would you do? Create multiple copies of each @@ -161,27 +161,36 @@ public class SoulEatingEnchantment implements Enchantment { Here are both hierarchies in action: ```java +LOGGER.info("The knight receives an enchanted sword."); var enchantedSword = new Sword(new SoulEatingEnchantment()); enchantedSword.wield(); enchantedSword.swing(); enchantedSword.unwield(); -// The sword is wielded. -// The item spreads bloodlust. -// The sword is swinged. -// The item eats the soul of enemies. -// The sword is unwielded. -// Bloodlust slowly disappears. +LOGGER.info("The valkyrie receives an enchanted hammer."); var hammer = new Hammer(new FlyingEnchantment()); hammer.wield(); hammer.swing(); hammer.unwield(); -// The hammer is wielded. -// The item begins to glow faintly. -// The hammer is swinged. -// The item flies and strikes the enemies finally returning to owner's hand. -// The hammer is unwielded. -// The item's glow fades. +``` + +Here's the console output. + +``` +The knight receives an enchanted sword. +The sword is wielded. +The item spreads bloodlust. +The sword is swung. +The item eats the soul of enemies. +The sword is unwielded. +Bloodlust slowly disappears. +The valkyrie receives an enchanted hammer. +The hammer is wielded. +The item begins to glow faintly. +The hammer is swung. +The item flies and strikes the enemies finally returning to owner's hand. +The hammer is unwielded. +The item's glow fades. ``` ## Class diagram diff --git a/builder/README.md b/builder/README.md index 9db1b9e93..54fb3de5b 100644 --- a/builder/README.md +++ b/builder/README.md @@ -16,11 +16,11 @@ process can create different representations. ## Explanation -Real world example +Real-world example > Imagine a character generator for a role-playing game. The easiest option is to let the computer > create the character for you. If you want to manually select the character details like -> profession, gender, hair color etc. the character generation becomes a step-by-step process that +> profession, gender, hair color, etc. the character generation becomes a step-by-step process that > completes when all the selections are ready. In plain words @@ -49,7 +49,7 @@ anti-pattern. **Programmatic Example** -The sane alternative is to use the Builder pattern. First of all we have our hero that we want to +The sane alternative is to use the Builder pattern. First of all, we have our hero that we want to create: ```java @@ -134,7 +134,7 @@ Use the Builder pattern when * The algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled * The construction process must allow different representations for the object that's constructed -## Real world examples +## Known uses * [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html) * [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) as well as similar buffers such as FloatBuffer, IntBuffer and so on. diff --git a/chain/README.md b/chain-of-responsibility/README.md similarity index 86% rename from chain/README.md rename to chain-of-responsibility/README.md index 28fefc847..a6d94499c 100644 --- a/chain/README.md +++ b/chain-of-responsibility/README.md @@ -1,8 +1,8 @@ --- layout: pattern title: Chain of responsibility -folder: chain -permalink: /patterns/chain/ +folder: chain-of-responsibility +permalink: /patterns/chain-of-responsibility/ categories: Behavioral language: en tags: @@ -10,16 +10,17 @@ tags: --- ## Intent + Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it. ## Explanation -Real world example +Real-world example > The Orc King gives loud orders to his army. The closest one to react is the commander, then -> officer and then soldier. The commander, officer and soldier here form a chain of responsibility. +> an officer, and then a soldier. The commander, officer, and soldier form a chain of responsibility. In plain words @@ -35,7 +36,7 @@ Wikipedia says **Programmatic Example** -Translating our example with the orcs from above. First we have the `Request` class: +Translating our example with the orcs from above. First, we have the `Request` class: ```java public class Request { @@ -66,7 +67,7 @@ public enum RequestType { } ``` -Then the request handler hierarchy +Next, we show the request handler hierarchy. ```java @Slf4j @@ -116,7 +117,7 @@ public class OrcCommander extends RequestHandler { ``` -Then we have the Orc King who gives the orders and forms the chain +The Orc King gives the orders and forms the chain. ```java public class OrcKing { @@ -136,18 +137,26 @@ public class OrcKing { } ``` -Then it is used as follows +The chain of responsibility in action. ```java var king = new OrcKing(); -king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); // Orc commander handling request "defend castle" -king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner")); // Orc officer handling request "torture prisoner" -king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); // Orc soldier handling request "collect tax" +king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); +king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner")); +king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); +``` + +The console output. + +``` +Orc commander handling request "defend castle" +Orc officer handling request "torture prisoner" +Orc soldier handling request "collect tax" ``` ## Class diagram -![alt text](./etc/chain.urm.png "Chain of Responsibility class diagram") +![alt text](./etc/chain-of-responsibility.urm.png "Chain of Responsibility class diagram") ## Applicability @@ -157,7 +166,7 @@ Use Chain of Responsibility when * You want to issue a request to one of several objects without specifying the receiver explicitly. * The set of objects that can handle a request should be specified dynamically. -## Real world examples +## Known uses * [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29) * [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html) diff --git a/chain/etc/chain.urm.png b/chain-of-responsibility/etc/chain-of-responsibility.urm.png similarity index 100% rename from chain/etc/chain.urm.png rename to chain-of-responsibility/etc/chain-of-responsibility.urm.png diff --git a/chain/etc/chain.urm.puml b/chain-of-responsibility/etc/chain-of-responsibility.urm.puml similarity index 100% rename from chain/etc/chain.urm.puml rename to chain-of-responsibility/etc/chain-of-responsibility.urm.puml diff --git a/chain/pom.xml b/chain-of-responsibility/pom.xml similarity index 97% rename from chain/pom.xml rename to chain-of-responsibility/pom.xml index 211b38ca4..8482fad42 100644 --- a/chain/pom.xml +++ b/chain-of-responsibility/pom.xml @@ -31,7 +31,7 @@ java-design-patterns 1.25.0-SNAPSHOT - chain + chain-of-responsibility org.junit.jupiter diff --git a/chain/src/main/java/com/iluwatar/chain/App.java b/chain-of-responsibility/src/main/java/com/iluwatar/chain/App.java similarity index 100% rename from chain/src/main/java/com/iluwatar/chain/App.java rename to chain-of-responsibility/src/main/java/com/iluwatar/chain/App.java diff --git a/chain/src/main/java/com/iluwatar/chain/OrcCommander.java b/chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcCommander.java similarity index 100% rename from chain/src/main/java/com/iluwatar/chain/OrcCommander.java rename to chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcCommander.java diff --git a/chain/src/main/java/com/iluwatar/chain/OrcKing.java b/chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcKing.java similarity index 100% rename from chain/src/main/java/com/iluwatar/chain/OrcKing.java rename to chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcKing.java diff --git a/chain/src/main/java/com/iluwatar/chain/OrcOfficer.java b/chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcOfficer.java similarity index 100% rename from chain/src/main/java/com/iluwatar/chain/OrcOfficer.java rename to chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcOfficer.java diff --git a/chain/src/main/java/com/iluwatar/chain/OrcSoldier.java b/chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcSoldier.java similarity index 100% rename from chain/src/main/java/com/iluwatar/chain/OrcSoldier.java rename to chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcSoldier.java diff --git a/chain/src/main/java/com/iluwatar/chain/Request.java b/chain-of-responsibility/src/main/java/com/iluwatar/chain/Request.java similarity index 100% rename from chain/src/main/java/com/iluwatar/chain/Request.java rename to chain-of-responsibility/src/main/java/com/iluwatar/chain/Request.java diff --git a/chain/src/main/java/com/iluwatar/chain/RequestHandler.java b/chain-of-responsibility/src/main/java/com/iluwatar/chain/RequestHandler.java similarity index 100% rename from chain/src/main/java/com/iluwatar/chain/RequestHandler.java rename to chain-of-responsibility/src/main/java/com/iluwatar/chain/RequestHandler.java diff --git a/chain/src/main/java/com/iluwatar/chain/RequestType.java b/chain-of-responsibility/src/main/java/com/iluwatar/chain/RequestType.java similarity index 100% rename from chain/src/main/java/com/iluwatar/chain/RequestType.java rename to chain-of-responsibility/src/main/java/com/iluwatar/chain/RequestType.java diff --git a/chain/src/test/java/com/iluwatar/chain/AppTest.java b/chain-of-responsibility/src/test/java/com/iluwatar/chain/AppTest.java similarity index 100% rename from chain/src/test/java/com/iluwatar/chain/AppTest.java rename to chain-of-responsibility/src/test/java/com/iluwatar/chain/AppTest.java diff --git a/chain/src/test/java/com/iluwatar/chain/OrcKingTest.java b/chain-of-responsibility/src/test/java/com/iluwatar/chain/OrcKingTest.java similarity index 100% rename from chain/src/test/java/com/iluwatar/chain/OrcKingTest.java rename to chain-of-responsibility/src/test/java/com/iluwatar/chain/OrcKingTest.java diff --git a/command/README.md b/command/README.md index d29c213cb..03122c410 100644 --- a/command/README.md +++ b/command/README.md @@ -1,4 +1,4 @@ ---- + --- layout: pattern title: Command folder: command @@ -19,7 +19,7 @@ Encapsulate a request as an object, thereby letting you parameterize clients wit requests, queue or log requests, and support undoable operations. ## Explanation -Real world example +Real-world example > There is a wizard casting spells on a goblin. The spells are executed on the goblin one by one. > The first spell shrinks the goblin and the second makes him invisible. Then the wizard reverses @@ -135,7 +135,7 @@ public class Goblin extends Target { } ``` -Finally we have the wizard in main function who casts spell +Finally, we have the wizard in the main function casting spells. ```java public static void main(String[] args) { @@ -202,32 +202,29 @@ Use the Command pattern when you want to: * Parameterize objects by an action to perform. You can express such parameterization in a procedural language with a callback function, that is, a function that's registered somewhere to be called at a later point. Commands are an object-oriented replacement for callbacks. -* Specify, queue, and execute requests at different times. A Command object can have a lifetime +* Specify, queue, and execute requests at different times. A Command object can have a life independent of the original request. If the receiver of a request can be represented in an address space-independent way, then you can transfer a command object for the request to a different process and fulfill the request there. * Support undo. The Command's execute operation can store state for reversing its effects in the command itself. The Command interface must have an added un-execute operation that reverses the effects of a previous call to execute. The executed commands are stored in a history list. -Unlimited-level undo and redo is achieved by traversing this list backwards and forwards calling -un-execute and execute, respectively. +Unlimited-level undo and redo functionality is achieved by traversing this list backward and forward + calling un-execute and execute, respectively. * Support logging changes so that they can be reapplied in case of a system crash. By augmenting the Command interface with load and store operations, you can keep a persistent log of changes. -Recovering from a crash involves reloading logged commands from disk and re-executing them with +Recovering from a crash involves reloading logged commands from the disk and re-executing them with the execute operation. * Structure a system around high-level operations build on primitive operations. Such a structure is -common in information systems that support transactions. A transaction encapsulates a set of changes -to data. The Command pattern offers a way to model transactions. Commands have a common interface, +common in information systems that support transactions. A transaction encapsulates a set of data +changes. The Command pattern offers a way to model transactions. Commands have a common interface, letting you invoke all transactions the same way. The pattern also makes it easy to extend the system with new transactions. +* Keep a history of requests. +* Implement callback functionality. +* Implement the undo functionality. -## Typical Use Case - -* To keep a history of requests -* Implement callback functionality -* Implement the undo functionality - -## Real world examples +## Known uses * [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html) * [org.junit.runners.model.Statement](https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/runners/model/Statement.java) diff --git a/command/src/main/java/com/iluwatar/command/App.java b/command/src/main/java/com/iluwatar/command/App.java index 92e1a1e70..54ffeac44 100644 --- a/command/src/main/java/com/iluwatar/command/App.java +++ b/command/src/main/java/com/iluwatar/command/App.java @@ -26,7 +26,7 @@ package com.iluwatar.command; /** * The Command pattern is a behavioral design pattern in which an object is used to encapsulate all * information needed to perform an action or trigger an event at a later time. This information - * includes the method name, the object that owns the method and values for the method parameters. + * includes the method name, the object that owns the method, and values for the method parameters. * *

Four terms always associated with the command pattern are command, receiver, invoker and * client. A command object (spell) knows about the receiver (target) and invokes a method of the diff --git a/composite/README.md b/composite/README.md index 013ab845d..3ce7bc951 100644 --- a/composite/README.md +++ b/composite/README.md @@ -16,15 +16,15 @@ treat individual objects and compositions of objects uniformly. ## Explanation -Real world example +Real-world example > Every sentence is composed of words which are in turn composed of characters. Each of these -> objects is printable and they can have something printed before or after them like sentence always -> ends with full stop and word always has space before it. +> objects are printable and they can have something printed before or after them like sentence +> always ends with full stop and word always has space before it. In plain words -> Composite pattern lets clients treat the individual objects in a uniform manner. +> Composite pattern lets clients uniformly treat the individual objects. Wikipedia says @@ -154,10 +154,22 @@ public class Messenger { And then it can be used as: ```java -var orcMessage = new Messenger().messageFromOrcs(); -orcMessage.print(); // Where there is a whip there is a way. -var elfMessage = new Messenger().messageFromElves(); -elfMessage.print(); // Much wind pours from your mouth. +var messenger = new Messenger(); + +LOGGER.info("Message from the orcs: "); +messenger.messageFromOrcs().print(); + +LOGGER.info("Message from the elves: "); +messenger.messageFromElves().print(); +``` + +The console output: + +``` +Message from the orcs: + Where there is a whip there is a way. +Message from the elves: + Much wind pours from your mouth. ``` ## Class diagram @@ -172,7 +184,7 @@ Use the Composite pattern when * You want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly. -## Real world examples +## Known uses * [java.awt.Container](http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html) and [java.awt.Component](http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html) * [Apache Wicket](https://github.com/apache/wicket) component tree, see [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java) and [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java) diff --git a/composite/src/main/java/com/iluwatar/composite/App.java b/composite/src/main/java/com/iluwatar/composite/App.java index 0660557ca..19a19db0d 100644 --- a/composite/src/main/java/com/iluwatar/composite/App.java +++ b/composite/src/main/java/com/iluwatar/composite/App.java @@ -45,14 +45,13 @@ public class App { * @param args command line args */ public static void main(String[] args) { + + var messenger = new Messenger(); + LOGGER.info("Message from the orcs: "); + messenger.messageFromOrcs().print(); - var orcMessage = new Messenger().messageFromOrcs(); - orcMessage.print(); - - LOGGER.info("\nMessage from the elves: "); - - var elfMessage = new Messenger().messageFromElves(); - elfMessage.print(); + LOGGER.info("Message from the elves: "); + messenger.messageFromElves().print(); } } diff --git a/composite/src/main/java/com/iluwatar/composite/Sentence.java b/composite/src/main/java/com/iluwatar/composite/Sentence.java index 239c64d19..91c4182c9 100644 --- a/composite/src/main/java/com/iluwatar/composite/Sentence.java +++ b/composite/src/main/java/com/iluwatar/composite/Sentence.java @@ -39,6 +39,6 @@ public class Sentence extends LetterComposite { @Override protected void printThisAfter() { - System.out.print("."); + System.out.print(".\n"); } } diff --git a/decorator/README.md b/decorator/README.md index 42577346d..bc5623726 100644 --- a/decorator/README.md +++ b/decorator/README.md @@ -6,7 +6,7 @@ permalink: /patterns/decorator/ categories: Structural language: en tags: - - Gang Of Four + - Gang of Four - Extensibility --- @@ -21,9 +21,9 @@ alternative to subclassing for extending functionality. ## Explanation -Real world example +Real-world example -> There is an angry troll living in the nearby hills. Usually it goes bare handed but sometimes it +> There is an angry troll living in the nearby hills. Usually, it goes bare-handed but sometimes it > has a weapon. To arm the troll it's not necessary to create a new troll but to decorate it > dynamically with a suitable weapon. @@ -72,7 +72,7 @@ public class SimpleTroll implements Troll { } ``` -Next we want to add club for the troll. We can do it dynamically by using a decorator: +Next, we want to add a club for the troll. We can do it dynamically by using a decorator: ```java @Slf4j @@ -106,23 +106,33 @@ Here's the troll in action: ```java // simple troll +LOGGER.info("A simple looking troll approaches."); var troll = new SimpleTroll(); -troll.attack(); // The troll tries to grab you! -troll.fleeBattle(); // The troll shrieks in horror and runs away! +troll.attack(); +troll.fleeBattle(); +LOGGER.info("Simple troll power: {}.\n", troll.getAttackPower()); // change the behavior of the simple troll by adding a decorator +LOGGER.info("A troll with huge club surprises you."); var clubbedTroll = new ClubbedTroll(troll); -clubbedTroll.attack(); // The troll tries to grab you! The troll swings at you with a club! -clubbedTroll.fleeBattle(); // The troll shrieks in horror and runs away! +clubbedTroll.attack(); +clubbedTroll.fleeBattle(); +LOGGER.info("Clubbed troll power: {}.\n", clubbedTroll.getAttackPower()); ``` Program output: ```java +A simple looking troll approaches. The troll tries to grab you! The troll shrieks in horror and runs away! -The troll tries to grab you! The troll swings at you with a club! +Simple troll power: 10. + +A troll with huge club surprises you. +The troll tries to grab you! +The troll swings at you with a club! The troll shrieks in horror and runs away! +Clubbed troll power: 20. ``` ## Class diagram @@ -140,11 +150,11 @@ affecting other objects. are possible and would produce an explosion of subclasses to support every combination. Or a class definition may be hidden or otherwise unavailable for subclassing. -## Tutorial +## Tutorials * [Decorator Pattern Tutorial](https://www.journaldev.com/1540/decorator-design-pattern-in-java-example) -## Real world examples +## Known uses * [java.io.InputStream](http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html), [java.io.OutputStream](http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html), [java.io.Reader](http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html) and [java.io.Writer](http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html) diff --git a/decorator/src/main/java/com/iluwatar/decorator/App.java b/decorator/src/main/java/com/iluwatar/decorator/App.java index 90ea972f6..dcd4ebc4e 100644 --- a/decorator/src/main/java/com/iluwatar/decorator/App.java +++ b/decorator/src/main/java/com/iluwatar/decorator/App.java @@ -50,13 +50,13 @@ public class App { var troll = new SimpleTroll(); troll.attack(); troll.fleeBattle(); - LOGGER.info("Simple troll power {}.\n", troll.getAttackPower()); + LOGGER.info("Simple troll power: {}.\n", troll.getAttackPower()); // change the behavior of the simple troll by adding a decorator LOGGER.info("A troll with huge club surprises you."); var clubbedTroll = new ClubbedTroll(troll); clubbedTroll.attack(); clubbedTroll.fleeBattle(); - LOGGER.info("Clubbed troll power {}.\n", clubbedTroll.getAttackPower()); + LOGGER.info("Clubbed troll power: {}.\n", clubbedTroll.getAttackPower()); } } diff --git a/facade/README.md b/facade/README.md index f37cfad8b..50f5091f7 100644 --- a/facade/README.md +++ b/facade/README.md @@ -17,7 +17,7 @@ interface that makes the subsystem easier to use. ## Explanation -Real world example +Real-world example > How does a goldmine work? "Well, the miners go down there and dig gold!" you say. That is what you > believe because you are using a simple interface that goldmine provides on the outside, internally diff --git a/factory-method/README.md b/factory-method/README.md index 1d41d7d1b..813a68445 100644 --- a/factory-method/README.md +++ b/factory-method/README.md @@ -7,7 +7,7 @@ categories: Creational language: en tags: - Extensibility - - Gang Of Four + - Gang of Four --- ## Also known as @@ -21,7 +21,7 @@ Factory Method lets a class defer instantiation to subclasses. ## Explanation -Real world example +Real-world example > Blacksmith manufactures weapons. Elves require Elvish weapons and orcs require Orcish weapons. > Depending on the customer at hand the right type of blacksmith is summoned. @@ -40,7 +40,7 @@ Wikipedia says **Programmatic Example** -Taking our blacksmith example above. First of all we have a `Blacksmith` interface and some +Taking our blacksmith example above. First of all, we have a `Blacksmith` interface and some implementations for it: ```java @@ -65,15 +65,25 @@ When the customers come, the correct type of blacksmith is summoned and requeste manufactured: ```java -var blacksmith = new ElfBlacksmith(); -blacksmith.manufactureWeapon(WeaponType.SPEAR); -blacksmith.manufactureWeapon(WeaponType.AXE); +Blacksmith blacksmith = new OrcBlacksmith(); +Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR); +LOGGER.info("{} manufactured {}", blacksmith, weapon); +weapon = blacksmith.manufactureWeapon(WeaponType.AXE); +LOGGER.info("{} manufactured {}", blacksmith, weapon); + +blacksmith = new ElfBlacksmith(); +weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR); +LOGGER.info("{} manufactured {}", blacksmith, weapon); +weapon = blacksmith.manufactureWeapon(WeaponType.AXE); +LOGGER.info("{} manufactured {}", blacksmith, weapon); ``` Program output: -```java -// Elven spear -// Elven axe +``` +The orc blacksmith manufactured an orcish spear +The orc blacksmith manufactured an orcish axe +The elf blacksmith manufactured an elven spear +The elf blacksmith manufactured an elven axe ``` ## Class diagram @@ -89,7 +99,7 @@ Use the Factory Method pattern when: * Classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate. -## Real world examples +## Known uses * [java.util.Calendar](http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--) * [java.util.ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-) diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/App.java b/factory-method/src/main/java/com/iluwatar/factory/method/App.java index 126114a84..b76a918d1 100644 --- a/factory-method/src/main/java/com/iluwatar/factory/method/App.java +++ b/factory-method/src/main/java/com/iluwatar/factory/method/App.java @@ -26,7 +26,7 @@ package com.iluwatar.factory.method; import lombok.extern.slf4j.Slf4j; /** - * The Factory Method is a creational design pattern which uses factory methods to deal with the + * The Factory Method is a creational design pattern that uses factory methods to deal with the * problem of creating objects without specifying the exact class of object that will be created. * This is done by creating objects via calling a factory method either specified in an interface * and implemented by child classes, or implemented in a base class and optionally overridden by @@ -41,39 +41,22 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class App { - private final Blacksmith blacksmith; - - /** - * Creates an instance of App which will use blacksmith to manufacture - * the weapons for war. - * App is unaware which concrete implementation of {@link Blacksmith} it is using. - * The decision of which blacksmith implementation to use may depend on configuration, or - * the type of rival in war. - * @param blacksmith a non-null implementation of blacksmith - */ - public App(Blacksmith blacksmith) { - this.blacksmith = blacksmith; - } - /** * Program entry point. - * * @param args command line args */ public static void main(String[] args) { - // Lets go to war with Orc weapons - var app = new App(new OrcBlacksmith()); - app.manufactureWeapons(); - // Lets go to war with Elf weapons - app = new App(new ElfBlacksmith()); - app.manufactureWeapons(); - } - - private void manufactureWeapons() { - var weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR); - LOGGER.info(weapon.toString()); + Blacksmith blacksmith = new OrcBlacksmith(); + Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR); + LOGGER.info("{} manufactured {}", blacksmith, weapon); weapon = blacksmith.manufactureWeapon(WeaponType.AXE); - LOGGER.info(weapon.toString()); + LOGGER.info("{} manufactured {}", blacksmith, weapon); + + blacksmith = new ElfBlacksmith(); + weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR); + LOGGER.info("{} manufactured {}", blacksmith, weapon); + weapon = blacksmith.manufactureWeapon(WeaponType.AXE); + LOGGER.info("{} manufactured {}", blacksmith, weapon); } } diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/ElfBlacksmith.java b/factory-method/src/main/java/com/iluwatar/factory/method/ElfBlacksmith.java index d801f43b8..a7bbbd58f 100644 --- a/factory-method/src/main/java/com/iluwatar/factory/method/ElfBlacksmith.java +++ b/factory-method/src/main/java/com/iluwatar/factory/method/ElfBlacksmith.java @@ -44,4 +44,8 @@ public class ElfBlacksmith implements Blacksmith { return ELFARSENAL.get(weaponType); } + @Override + public String toString() { + return "The elf blacksmith"; + } } diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/ElfWeapon.java b/factory-method/src/main/java/com/iluwatar/factory/method/ElfWeapon.java index 321f24873..0ba2f716b 100644 --- a/factory-method/src/main/java/com/iluwatar/factory/method/ElfWeapon.java +++ b/factory-method/src/main/java/com/iluwatar/factory/method/ElfWeapon.java @@ -37,6 +37,6 @@ public class ElfWeapon implements Weapon { @Override public String toString() { - return "Elven " + weaponType; + return "an elven " + weaponType; } } diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/OrcBlacksmith.java b/factory-method/src/main/java/com/iluwatar/factory/method/OrcBlacksmith.java index 1ef87b86f..139dda7df 100644 --- a/factory-method/src/main/java/com/iluwatar/factory/method/OrcBlacksmith.java +++ b/factory-method/src/main/java/com/iluwatar/factory/method/OrcBlacksmith.java @@ -43,4 +43,9 @@ public class OrcBlacksmith implements Blacksmith { public Weapon manufactureWeapon(WeaponType weaponType) { return ORCARSENAL.get(weaponType); } + + @Override + public String toString() { + return "The orc blacksmith"; + } } diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/OrcWeapon.java b/factory-method/src/main/java/com/iluwatar/factory/method/OrcWeapon.java index 560c7aaf7..f87be2b00 100644 --- a/factory-method/src/main/java/com/iluwatar/factory/method/OrcWeapon.java +++ b/factory-method/src/main/java/com/iluwatar/factory/method/OrcWeapon.java @@ -37,6 +37,6 @@ public class OrcWeapon implements Weapon { @Override public String toString() { - return "Orcish " + weaponType; + return "an orcish " + weaponType; } } diff --git a/factory/README.md b/factory/README.md index 147ae546c..dd5582bec 100644 --- a/factory/README.md +++ b/factory/README.md @@ -16,16 +16,17 @@ tags: ## Intent -Providing a static method encapsulated in a class called factory, in order to hide the -implementation logic and makes client code focus on usage rather then initialization new objects. +Providing a static method encapsulated in a class called the factory, to hide the implementation +logic and make client code focus on usage rather than initializing new objects. ## Explanation -Real world example +Real-world example -> Lets say we have a web application connected to SQLServer, but now we want to switch to Oracle. To -> do so without modifying existing source code, we need to implements Simple Factory pattern, in -> which a static method can be invoked to create connection to a given database. +> Imagine an alchemist who is about to manufacture coins. The alchemist must be able to create both +> gold and copper coins and switching between them must be possible without modifying the existing +> source code. The factory pattern makes it possible by providing a static construction method which +> can be called with relevant parameters. Wikipedia says @@ -34,16 +35,16 @@ Wikipedia says **Programmatic Example** -We have an interface `Car` and two implementations `Ford` and `Ferrari`. +We have an interface `Coin` and two implementations `GoldCoin` and `CopperCoin`. ```java -public interface Car { +public interface Coin { String getDescription(); } -public class Ford implements Car { +public class GoldCoin implements Coin { - static final String DESCRIPTION = "This is Ford."; + static final String DESCRIPTION = "This is a gold coin."; @Override public String getDescription() { @@ -51,9 +52,9 @@ public class Ford implements Car { } } -public class Ferrari implements Car { +public class CopperCoin implements Coin { - static final String DESCRIPTION = "This is Ferrari."; + static final String DESCRIPTION = "This is a copper coin."; @Override public String getDescription() { @@ -62,51 +63,48 @@ public class Ferrari implements Car { } ``` -Enumeration above represents types of cars that we support (`Ford` and `Ferrari`). +Enumeration above represents types of coins that we support (`GoldCoin` and `CopperCoin`). ```java -public enum CarType { - - FORD(Ford::new), - FERRARI(Ferrari::new); - - private final Supplier constructor; - - CarType(Supplier constructor) { - this.constructor = constructor; - } - - public Supplier getConstructor() { - return this.constructor; - } +@RequiredArgsConstructor +@Getter +public enum CoinType { + + COPPER(CopperCoin::new), + GOLD(GoldCoin::new); + + private final Supplier constructor; } ``` -Then we have the static method `getCar` to create car objects encapsulated in the factory class -`CarsFactory`. + +Then we have the static method `getCoin` to create coin objects encapsulated in the factory class +`CoinFactory`. ```java -public class CarsFactory { - - public static Car getCar(CarType type) { +public class CoinFactory { + + public static Coin getCoin(CoinType type) { return type.getConstructor().get(); } } ``` -Now on the client code we can create different types of cars using the factory class. +Now on the client code we can create different types of coins using the factory class. ```java -var car1 = CarsFactory.getCar(CarType.FORD); -var car2 = CarsFactory.getCar(CarType.FERRARI); -LOGGER.info(car1.getDescription()); -LOGGER.info(car2.getDescription()); +LOGGER.info("The alchemist begins his work."); +var coin1 = CoinFactory.getCoin(CoinType.COPPER); +var coin2 = CoinFactory.getCoin(CoinType.GOLD); +LOGGER.info(coin1.getDescription()); +LOGGER.info(coin2.getDescription()); ``` Program output: ```java -This is Ford. -This is Ferrari. +The alchemist begins his work. +This is a copper coin. +This is a gold coin. ``` ## Class Diagram @@ -115,7 +113,7 @@ This is Ferrari. ## Applicability -Use the Simple Factory pattern when you only care about the creation of a object, not how to create +Use the factory pattern when you only care about the creation of a object, not how to create and manage it. Pros @@ -127,13 +125,13 @@ Cons * The code becomes more complicated than it should be. -## Real world examples +## Known uses * [java.util.Calendar#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--) * [java.util.ResourceBundle#getBundle()](https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-) * [java.text.NumberFormat#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--) * [java.nio.charset.Charset#forName()](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-) -* [java.net.URLStreamHandlerFactory#createURLStreamHandler(String)](https://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html) (Returns different singleton objects, depending on a protocol) +* [java.net.URLStreamHandlerFactory#createURLStreamHandler(String)](https://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html) (returns different singleton objects, depending on a protocol) * [java.util.EnumSet#of()](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of(E)) * [javax.xml.bind.JAXBContext#createMarshaller()](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--) and other similar methods. diff --git a/factory/etc/factory.urm.png b/factory/etc/factory.urm.png index 2ba39a571c4efd3d5cfd45854f0d26c843fafd8e..4b3420792e06f2f55e1d49d0fcac29e6fe8c2dd7 100644 GIT binary patch literal 29351 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 diff --git a/factory/etc/factory.urm.puml b/factory/etc/factory.urm.puml index 9eded6328..eb08a4596 100644 --- a/factory/etc/factory.urm.puml +++ b/factory/etc/factory.urm.puml @@ -5,31 +5,32 @@ package com.iluwatar.factory { + App() + main(args : String[]) {static} } - interface Car { + interface Coin { + getDescription() : String {abstract} } - class CarsFactory { - + CarsFactory() - + getCar(type : CarType) : Car {static} + class CoinFactory { + + CoinFactory() + + getCoin(type : CoinType) : Coin {static} } - ~enum CarType { - + FERRARI {static} - + FORD {static} - + valueOf(name : String) : CarType {static} - + values() : CarType[] {static} + enum CoinType { + + COPPER {static} + + GOLD {static} + - constructor : Supplier + + getConstructor() : Supplier + + valueOf(name : String) : CoinType {static} + + values() : CoinType[] {static} } - class Ferrari { + class CopperCoin { ~ DESCRIPTION : String {static} - + Ferrari() + + CopperCoin() + getDescription() : String } - class Ford { + class GoldCoin { ~ DESCRIPTION : String {static} - + Ford() + + GoldCoin() + getDescription() : String } } -CarType ..+ CarsFactory -Ferrari ..|> Car -Ford ..|> Car +CopperCoin ..|> Coin +GoldCoin ..|> Coin @enduml \ No newline at end of file diff --git a/factory/src/main/java/com/iluwatar/factory/App.java b/factory/src/main/java/com/iluwatar/factory/App.java index 732f5458f..6c10fafcb 100644 --- a/factory/src/main/java/com/iluwatar/factory/App.java +++ b/factory/src/main/java/com/iluwatar/factory/App.java @@ -30,8 +30,8 @@ import lombok.extern.slf4j.Slf4j; * create and return objects of varying classes, in order to hide the implementation logic * and makes client code focus on usage rather then objects initialization and management. * - *

In this example the CarFactory is the factory class and it provides a static method to - * create different cars. + *

In this example an alchemist manufactures coins. CoinFactory is the factory class and it + * provides a static method to create different types of coins. */ @Slf4j @@ -41,9 +41,10 @@ public class App { * Program main entry point. */ public static void main(String[] args) { - var car1 = CarsFactory.getCar(CarType.FORD); - var car2 = CarsFactory.getCar(CarType.FERRARI); - LOGGER.info(car1.getDescription()); - LOGGER.info(car2.getDescription()); + LOGGER.info("The alchemist begins his work."); + var coin1 = CoinFactory.getCoin(CoinType.COPPER); + var coin2 = CoinFactory.getCoin(CoinType.GOLD); + LOGGER.info(coin1.getDescription()); + LOGGER.info(coin2.getDescription()); } } diff --git a/factory/src/main/java/com/iluwatar/factory/Car.java b/factory/src/main/java/com/iluwatar/factory/Coin.java similarity index 96% rename from factory/src/main/java/com/iluwatar/factory/Car.java rename to factory/src/main/java/com/iluwatar/factory/Coin.java index e1e248fb4..3b4c1a52a 100644 --- a/factory/src/main/java/com/iluwatar/factory/Car.java +++ b/factory/src/main/java/com/iluwatar/factory/Coin.java @@ -24,9 +24,9 @@ package com.iluwatar.factory; /** - * Car interface. + * Coin interface. */ -public interface Car { +public interface Coin { String getDescription(); diff --git a/factory/src/main/java/com/iluwatar/factory/CarsFactory.java b/factory/src/main/java/com/iluwatar/factory/CoinFactory.java similarity index 87% rename from factory/src/main/java/com/iluwatar/factory/CarsFactory.java rename to factory/src/main/java/com/iluwatar/factory/CoinFactory.java index 941552065..3ff862a23 100644 --- a/factory/src/main/java/com/iluwatar/factory/CarsFactory.java +++ b/factory/src/main/java/com/iluwatar/factory/CoinFactory.java @@ -24,14 +24,14 @@ package com.iluwatar.factory; /** - * Factory of cars. + * Factory of coins. */ -public class CarsFactory { +public class CoinFactory { /** - * Factory method takes as parameter a car type and initiate the appropriate class. + * Factory method takes as a parameter the coin type and calls the appropriate class. */ - public static Car getCar(CarType type) { + public static Coin getCoin(CoinType type) { return type.getConstructor().get(); } } diff --git a/factory/src/main/java/com/iluwatar/factory/CarType.java b/factory/src/main/java/com/iluwatar/factory/CoinType.java similarity index 89% rename from factory/src/main/java/com/iluwatar/factory/CarType.java rename to factory/src/main/java/com/iluwatar/factory/CoinType.java index 074ea32bc..49e0c8166 100644 --- a/factory/src/main/java/com/iluwatar/factory/CarType.java +++ b/factory/src/main/java/com/iluwatar/factory/CoinType.java @@ -28,15 +28,14 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; /** - * Enumeration for different types of cars. + * Enumeration for different types of coins. */ @RequiredArgsConstructor @Getter -public enum CarType { +public enum CoinType { - FORD(Ford::new), - FERRARI(Ferrari::new); - - private final Supplier constructor; + COPPER(CopperCoin::new), + GOLD(GoldCoin::new); + private final Supplier constructor; } diff --git a/factory/src/main/java/com/iluwatar/factory/Ferrari.java b/factory/src/main/java/com/iluwatar/factory/CopperCoin.java similarity index 90% rename from factory/src/main/java/com/iluwatar/factory/Ferrari.java rename to factory/src/main/java/com/iluwatar/factory/CopperCoin.java index c11ee3679..284355360 100644 --- a/factory/src/main/java/com/iluwatar/factory/Ferrari.java +++ b/factory/src/main/java/com/iluwatar/factory/CopperCoin.java @@ -24,11 +24,11 @@ package com.iluwatar.factory; /** - * Ferrari implementation. + * CopperCoin implementation. */ -public class Ferrari implements Car { +public class CopperCoin implements Coin { - static final String DESCRIPTION = "This is Ferrari."; + static final String DESCRIPTION = "This is a copper coin."; @Override public String getDescription() { diff --git a/factory/src/main/java/com/iluwatar/factory/Ford.java b/factory/src/main/java/com/iluwatar/factory/GoldCoin.java similarity index 90% rename from factory/src/main/java/com/iluwatar/factory/Ford.java rename to factory/src/main/java/com/iluwatar/factory/GoldCoin.java index d1091a00b..71eb8debb 100644 --- a/factory/src/main/java/com/iluwatar/factory/Ford.java +++ b/factory/src/main/java/com/iluwatar/factory/GoldCoin.java @@ -24,11 +24,11 @@ package com.iluwatar.factory; /** - * Ford implementation. + * GoldCoin implementation. */ -public class Ford implements Car { +public class GoldCoin implements Coin { - static final String DESCRIPTION = "This is Ford."; + static final String DESCRIPTION = "This is a gold coin."; @Override public String getDescription() { diff --git a/factory/src/test/java/com/iluwatar/factory/CarsFactoryTest.java b/factory/src/test/java/com/iluwatar/factory/CoinFactoryTest.java similarity index 88% rename from factory/src/test/java/com/iluwatar/factory/CarsFactoryTest.java rename to factory/src/test/java/com/iluwatar/factory/CoinFactoryTest.java index c29cbbeb4..fadccff55 100644 --- a/factory/src/test/java/com/iluwatar/factory/CarsFactoryTest.java +++ b/factory/src/test/java/com/iluwatar/factory/CoinFactoryTest.java @@ -27,12 +27,11 @@ import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; -class CarsFactoryTest { +class CoinFactoryTest { @Test - void shouldReturnFerrariInstance() { - final var ferrari = CarsFactory.getCar(CarType.FERRARI); - assertTrue(ferrari instanceof Ferrari); + void shouldReturnGoldCoinInstance() { + final var goldCoin = CoinFactory.getCoin(CoinType.GOLD); + assertTrue(goldCoin instanceof GoldCoin); } - } diff --git a/flyweight/README.md b/flyweight/README.md index 38af1f2dd..79ca511ba 100644 --- a/flyweight/README.md +++ b/flyweight/README.md @@ -6,7 +6,7 @@ permalink: /patterns/flyweight/ categories: Structural language: en tags: - - Gang Of Four + - Gang of Four - Performance --- @@ -16,11 +16,11 @@ Use sharing to support large numbers of fine-grained objects efficiently. ## Explanation -Real world example +Real-world example > Alchemist's shop has shelves full of magic potions. Many of the potions are the same so there is -> no need to create new object for each of them. Instead one object instance can represent multiple -> shelf items so memory footprint remains small. +> no need to create a new object for each of them. Instead, one object instance can represent +> multiple shelf items so the memory footprint remains small. In plain words @@ -36,7 +36,7 @@ Wikipedia says **Programmatic example** -Translating our alchemist shop example from above. First of all we have different potion types: +Translating our alchemist shop example from above. First of all, we have different potion types: ```java public interface Potion { @@ -104,27 +104,81 @@ public class PotionFactory { } ``` -And it can be used as below: +`AlchemistShop` contains two shelves of magic potions. The potions are created using the +aforementioned `PotionFactory`. ```java -var factory = new PotionFactory(); -factory.createPotion(PotionType.INVISIBILITY).drink(); // You become invisible. (Potion=6566818) -factory.createPotion(PotionType.HEALING).drink(); // You feel healed. (Potion=648129364) -factory.createPotion(PotionType.INVISIBILITY).drink(); // You become invisible. (Potion=6566818) -factory.createPotion(PotionType.HOLY_WATER).drink(); // You feel blessed. (Potion=1104106489) -factory.createPotion(PotionType.HOLY_WATER).drink(); // You feel blessed. (Potion=1104106489) -factory.createPotion(PotionType.HEALING).drink(); // You feel healed. (Potion=648129364) +@Slf4j +public class AlchemistShop { + + private final List topShelf; + private final List bottomShelf; + + public AlchemistShop() { + var factory = new PotionFactory(); + topShelf = List.of( + factory.createPotion(PotionType.INVISIBILITY), + factory.createPotion(PotionType.INVISIBILITY), + factory.createPotion(PotionType.STRENGTH), + factory.createPotion(PotionType.HEALING), + factory.createPotion(PotionType.INVISIBILITY), + factory.createPotion(PotionType.STRENGTH), + factory.createPotion(PotionType.HEALING), + factory.createPotion(PotionType.HEALING) + ); + bottomShelf = List.of( + factory.createPotion(PotionType.POISON), + factory.createPotion(PotionType.POISON), + factory.createPotion(PotionType.POISON), + factory.createPotion(PotionType.HOLY_WATER), + factory.createPotion(PotionType.HOLY_WATER) + ); + } + + public final List getTopShelf() { + return List.copyOf(this.topShelf); + } + + public final List getBottomShelf() { + return List.copyOf(this.bottomShelf); + } + + public void drinkPotions() { + LOGGER.info("Drinking top shelf potions\n"); + topShelf.forEach(Potion::drink); + LOGGER.info("Drinking bottom shelf potions\n"); + bottomShelf.forEach(Potion::drink); + } +} +``` + +In our scenario, a brave visitor enters the alchemist shop and drinks all the potions. + +```java +// create the alchemist shop with the potions +var alchemistShop = new AlchemistShop(); +// a brave visitor enters the alchemist shop and drinks all the potions +alchemistShop.drinkPotions(); ``` Program output: ```java -You become invisible. (Potion=6566818) -You feel healed. (Potion=648129364) -You become invisible. (Potion=6566818) -You feel blessed. (Potion=1104106489) -You feel blessed. (Potion=1104106489) -You feel healed. (Potion=648129364) +Drinking top shelf potions +You become invisible. (Potion=1509514333) +You become invisible. (Potion=1509514333) +You feel strong. (Potion=739498517) +You feel healed. (Potion=125130493) +You become invisible. (Potion=1509514333) +You feel strong. (Potion=739498517) +You feel healed. (Potion=125130493) +You feel healed. (Potion=125130493) +Drinking bottom shelf potions +Urgh! This is poisonous. (Potion=166239592) +Urgh! This is poisonous. (Potion=166239592) +Urgh! This is poisonous. (Potion=166239592) +You feel blessed. (Potion=991505714) +You feel blessed. (Potion=991505714) ``` ## Class diagram @@ -138,13 +192,13 @@ Flyweight pattern when all of the following are true: * An application uses a large number of objects. * Storage costs are high because of the sheer quantity of objects. -* Most object state can be made extrinsic. -* Many groups of objects may be replaced by relatively few shared objects once extrinsic state is -removed. +* Most of the object state can be made extrinsic. +* Many groups of objects may be replaced by relatively few shared objects once the extrinsic state + is removed. * The application doesn't depend on object identity. Since flyweight objects may be shared, identity tests will return true for conceptually distinct objects. -## Real world examples +## Known uses * [java.lang.Integer#valueOf(int)](http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#valueOf%28int%29) and similarly for Byte, Character and other wrapped types. diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java b/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java index 135712718..f96a9027c 100644 --- a/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java +++ b/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java @@ -78,12 +78,12 @@ public class AlchemistShop { } /** - * Enumerate potions. + * Drink all the potions. */ - public void enumerate() { - LOGGER.info("Enumerating top shelf potions\n"); + public void drinkPotions() { + LOGGER.info("Drinking top shelf potions"); topShelf.forEach(Potion::drink); - LOGGER.info("Enumerating bottom shelf potions\n"); + LOGGER.info("Drinking bottom shelf potions"); bottomShelf.forEach(Potion::drink); } } diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/App.java b/flyweight/src/main/java/com/iluwatar/flyweight/App.java index 1982d376e..ec08872bb 100644 --- a/flyweight/src/main/java/com/iluwatar/flyweight/App.java +++ b/flyweight/src/main/java/com/iluwatar/flyweight/App.java @@ -43,7 +43,9 @@ public class App { * @param args command line args */ public static void main(String[] args) { + // create the alchemist shop with the potions var alchemistShop = new AlchemistShop(); - alchemistShop.enumerate(); + // a brave visitor enters the alchemist shop and drinks all the potions + alchemistShop.drinkPotions(); } } diff --git a/interpreter/README.md b/interpreter/README.md index 01053aaba..92172c70c 100644 --- a/interpreter/README.md +++ b/interpreter/README.md @@ -10,22 +10,161 @@ tags: --- ## Intent -Given a language, define a representation for its grammar along -with an interpreter that uses the representation to interpret sentences in the -language. + +Given a language, define a representation for its grammar along with an interpreter that uses the +representation to interpret sentences in the language. + +## Explanation + +Real-world example + +> The halfling kids are learning basic math at school. They start from the very basics "1 + 1", +> "4 - 2", "5 + 5", and so forth. + +In plain words + +> Interpreter pattern interprets sentences in the desired language. + +Wikipedia says + +> In computer programming, the interpreter pattern is a design pattern that specifies how to +> evaluate sentences in a language. The basic idea is to have a class for each symbol (terminal or +> nonterminal) in a specialized computer language. The syntax tree of a sentence in the language +> is an instance of the composite pattern and is used to evaluate (interpret) the sentence for +> a client. + +**Programmatic example** + +To be able to interpret basic math, we need a hierarchy of expressions. The basic abstraction for +it is the `Expression` class. + +```java +public abstract class Expression { + + public abstract int interpret(); + + @Override + public abstract String toString(); +} +``` + +The simplest of the expressions is the `NumberExpression` that contains only a single integer +number. + +```java +public class NumberExpression extends Expression { + + private final int number; + + public NumberExpression(int number) { + this.number = number; + } + + public NumberExpression(String s) { + this.number = Integer.parseInt(s); + } + + @Override + public int interpret() { + return number; + } + + @Override + public String toString() { + return "number"; + } +} +``` + +The more complex expressions are operations such as `PlusExpression`, `MinusExpression`, and +`MultiplyExpression`. Here's the first of them, the others are similar. + +```java +public class PlusExpression extends Expression { + + private final Expression leftExpression; + private final Expression rightExpression; + + public PlusExpression(Expression leftExpression, Expression rightExpression) { + this.leftExpression = leftExpression; + this.rightExpression = rightExpression; + } + + @Override + public int interpret() { + return leftExpression.interpret() + rightExpression.interpret(); + } + + @Override + public String toString() { + return "+"; + } +} +``` + +Now we are able to show the interpreter pattern in action parsing some simple math. + +```java + // the halfling kids are learning some basic math at school + // define the math string we want to parse + final var tokenString = "4 3 2 - 1 + *"; + + // the stack holds the parsed expressions + var stack = new Stack(); + + // tokenize the string and go through them one by one + var tokenList = tokenString.split(" "); + for (var s : tokenList) { + if (isOperator(s)) { + // when an operator is encountered we expect that the numbers can be popped from the top of + // the stack + var rightExpression = stack.pop(); + var leftExpression = stack.pop(); + LOGGER.info("popped from stack left: {} right: {}", + leftExpression.interpret(), rightExpression.interpret()); + var operator = getOperatorInstance(s, leftExpression, rightExpression); + LOGGER.info("operator: {}", operator); + var result = operator.interpret(); + // the operation result is pushed on top of the stack + var resultExpression = new NumberExpression(result); + stack.push(resultExpression); + LOGGER.info("push result to stack: {}", resultExpression.interpret()); + } else { + // numbers are pushed on top of the stack + var i = new NumberExpression(s); + stack.push(i); + LOGGER.info("push to stack: {}", i.interpret()); + } + } + // in the end, the final result lies on top of the stack + LOGGER.info("result: {}", stack.pop().interpret()); +``` + +Executing the program produces the following console output. + +``` +popped from stack left: 1 right: 1 +operator: + +push result to stack: 2 +popped from stack left: 4 right: 2 +operator: * +push result to stack: 8 +result: 8 +``` ## Class diagram + ![alt text](./etc/interpreter_1.png "Interpreter") ## Applicability -Use the Interpreter pattern when there is a language to -interpret, and you can represent statements in the language as abstract syntax -trees. The Interpreter pattern works best when -* the grammar is simple. For complex grammars, the class hierarchy for the grammar becomes large and unmanageable. Tools such as parser generators are a better alternative in such cases. They can interpret expressions without building abstract syntax trees, which can save space and possibly time -* efficiency is not a critical concern. The most efficient interpreters are usually not implemented by interpreting parse trees directly but by first translating them into another form. For example, regular expressions are often transformed into state machines. But even then, the translator can be implemented by the Interpreter pattern, so the pattern is still applicable +Use the Interpreter pattern when there is a language to interpret, and you can represent statements +in the language as abstract syntax trees. The Interpreter pattern works best when -## Real world examples +* The grammar is simple. For complex grammars, the class hierarchy for the grammar becomes large and unmanageable. Tools such as parser generators are a better alternative in such cases. They can interpret expressions without building abstract syntax trees, which can save space and possibly time +* Efficiency is not a critical concern. The most efficient interpreters are usually not implemented by interpreting parse trees directly but by first translating them into another form. For example, regular expressions are often transformed into state machines. But even then, the translator can be implemented by the Interpreter pattern, so the pattern is still applicable + +## Known uses * [java.util.Pattern](http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html) * [java.text.Normalizer](http://docs.oracle.com/javase/8/docs/api/java/text/Normalizer.html) diff --git a/interpreter/src/main/java/com/iluwatar/interpreter/App.java b/interpreter/src/main/java/com/iluwatar/interpreter/App.java index ebff7b532..c4cfa2a49 100644 --- a/interpreter/src/main/java/com/iluwatar/interpreter/App.java +++ b/interpreter/src/main/java/com/iluwatar/interpreter/App.java @@ -34,25 +34,33 @@ import lombok.extern.slf4j.Slf4j; * *

In this example we use the Interpreter pattern to break sentences into expressions ({@link * Expression}) that can be evaluated and as a whole form the result. + * + *

Expressions can be evaluated using prefix, infix or postfix notations This sample uses + * postfix, where operator comes after the operands. + * */ @Slf4j public class App { /** * Program entry point. - * - *

Expressions can be evaluated using prefix, infix or postfix notations This sample uses - * postfix, where operator comes after the operands. - * - * @param args command line args + * @param args program arguments */ public static void main(String[] args) { - var tokenString = "4 3 2 - 1 + *"; + + // the halfling kids are learning some basic math at school + // define the math string we want to parse + final var tokenString = "4 3 2 - 1 + *"; + + // the stack holds the parsed expressions var stack = new Stack(); + // tokenize the string and go through them one by one var tokenList = tokenString.split(" "); for (var s : tokenList) { if (isOperator(s)) { + // when an operator is encountered we expect that the numbers can be popped from the top of + // the stack var rightExpression = stack.pop(); var leftExpression = stack.pop(); LOGGER.info("popped from stack left: {} right: {}", @@ -60,24 +68,36 @@ public class App { var operator = getOperatorInstance(s, leftExpression, rightExpression); LOGGER.info("operator: {}", operator); var result = operator.interpret(); + // the operation result is pushed on top of the stack var resultExpression = new NumberExpression(result); stack.push(resultExpression); LOGGER.info("push result to stack: {}", resultExpression.interpret()); } else { + // numbers are pushed on top of the stack var i = new NumberExpression(s); stack.push(i); LOGGER.info("push to stack: {}", i.interpret()); } } + // in the end, the final result lies on top of the stack LOGGER.info("result: {}", stack.pop().interpret()); } + /** + * Checks whether the input parameter is an operator. + * @param s input string + * @return true if the input parameter is an operator + */ public static boolean isOperator(String s) { return s.equals("+") || s.equals("-") || s.equals("*"); } /** - * Get expression for string. + * Returns correct expression based on the parameters. + * @param s input string + * @param left expression + * @param right expression + * @return expression */ public static Expression getOperatorInstance(String s, Expression left, Expression right) { switch (s) { @@ -85,8 +105,6 @@ public class App { return new PlusExpression(left, right); case "-": return new MinusExpression(left, right); - case "*": - return new MultiplyExpression(left, right); default: return new MultiplyExpression(left, right); } diff --git a/iterator/README.md b/iterator/README.md index e48402593..721b313f8 100644 --- a/iterator/README.md +++ b/iterator/README.md @@ -19,10 +19,10 @@ underlying representation. ## Explanation -Real world example +Real-world example > Treasure chest contains a set of magical items. There multiple types of items such as rings, -> potions and weapons. The items can be browsed by type using an iterator the treasure chest +> potions, and weapons. The items can be browsed by type using an iterator the treasure chest > provides. In plain words @@ -113,7 +113,7 @@ public interface Iterator { } ``` -In the following example we iterate through the ring type items found in the chest. +In the following example, we iterate through the ring-type items found in the chest. ```java var itemIterator = TREASURE_CHEST.iterator(ItemType.RING); @@ -145,7 +145,7 @@ Use the Iterator pattern * [How to Use Iterator?](http://www.tutorialspoint.com/java/java_using_iterator.htm) -## Real world examples +## Known uses * [java.util.Iterator](http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html) * [java.util.Enumeration](http://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html) diff --git a/mediator/README.md b/mediator/README.md index edb748a8f..627de4e28 100644 --- a/mediator/README.md +++ b/mediator/README.md @@ -11,21 +11,192 @@ tags: --- ## Intent -Define an object that encapsulates how a set of objects interact. -Mediator promotes loose coupling by keeping objects from referring to each -other explicitly, and it lets you vary their interaction independently. + +Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling +by keeping objects from referring to each other explicitly, and it lets you vary their interaction +independently. + +## Explanation + +Real-world example + +> Rogue, wizard, hobbit, and hunter have decided to join their forces and travel in the same +> party. To avoid coupling each member with each other, they use the party interface to +> communicate with each other. + +In plain words + +> Mediator decouples a set of classes by forcing their communications flow through a mediating +> object. + +Wikipedia says + +> In software engineering, the mediator pattern defines an object that encapsulates how a set of +> objects interact. This pattern is considered to be a behavioral pattern due to the way it can +> alter the program's running behavior. In object-oriented programming, programs often consist of +> many classes. Business logic and computation are distributed among these classes. However, as +> more classes are added to a program, especially during maintenance and/or refactoring, the +> problem of communication between these classes may become more complex. This makes the program +> harder to read and maintain. Furthermore, it can become difficult to change the program, since +> any change may affect code in several other classes. With the mediator pattern, communication +> between objects is encapsulated within a mediator object. Objects no longer communicate directly +> with each other, but instead communicate through the mediator. This reduces the dependencies +> between communicating objects, thereby reducing coupling. + +**Programmatic Example** + +In this example, the mediator encapsulates how a set of objects interact. Instead of referring to +each other directly they use the mediator interface. + +The party members `Rogue`, `Wizard`, `Hobbit`, and `Hunter` all inherit from the `PartyMemberBase` +implementing the `PartyMember` interface. + +```java +public interface PartyMember { + + void joinedParty(Party party); + + void partyAction(Action action); + + void act(Action action); +} + +@Slf4j +public abstract class PartyMemberBase implements PartyMember { + + protected Party party; + + @Override + public void joinedParty(Party party) { + LOGGER.info("{} joins the party", this); + this.party = party; + } + + @Override + public void partyAction(Action action) { + LOGGER.info("{} {}", this, action.getDescription()); + } + + @Override + public void act(Action action) { + if (party != null) { + LOGGER.info("{} {}", this, action); + party.act(this, action); + } + } + + @Override + public abstract String toString(); +} + +public class Rogue extends PartyMemberBase { + + @Override + public String toString() { + return "Rogue"; + } +} + +// Wizard, Hobbit, and Hunter are implemented similarly +``` + +Our mediator system consists of `Party` interface and its implementation. + +```java +public interface Party { + + void addMember(PartyMember member); + + void act(PartyMember actor, Action action); +} + +public class PartyImpl implements Party { + + private final List members; + + public PartyImpl() { + members = new ArrayList<>(); + } + + @Override + public void act(PartyMember actor, Action action) { + for (var member : members) { + if (!member.equals(actor)) { + member.partyAction(action); + } + } + } + + @Override + public void addMember(PartyMember member) { + members.add(member); + member.joinedParty(this); + } +} +``` + +Here's a demo showing the mediator pattern in action. + +```java + // create party and members + Party party = new PartyImpl(); + var hobbit = new Hobbit(); + var wizard = new Wizard(); + var rogue = new Rogue(); + var hunter = new Hunter(); + + // add party members + party.addMember(hobbit); + party.addMember(wizard); + party.addMember(rogue); + party.addMember(hunter); + + // perform actions -> the other party members + // are notified by the party + hobbit.act(Action.ENEMY); + wizard.act(Action.TALE); + rogue.act(Action.GOLD); + hunter.act(Action.HUNT); +``` + +Here's the console output from running the example. + +``` +Hobbit joins the party +Wizard joins the party +Rogue joins the party +Hunter joins the party +Hobbit spotted enemies +Wizard runs for cover +Rogue runs for cover +Hunter runs for cover +Wizard tells a tale +Hobbit comes to listen +Rogue comes to listen +Hunter comes to listen +Rogue found gold +Hobbit takes his share of the gold +Wizard takes his share of the gold +Hunter takes his share of the gold +Hunter hunted a rabbit +Hobbit arrives for dinner +Wizard arrives for dinner +Rogue arrives for dinner +``` ## Class diagram + ![alt text](./etc/mediator_1.png "Mediator") ## Applicability + Use the Mediator pattern when -* a set of objects communicate in well-defined but complex ways. The resulting interdependencies are unstructured and difficult to understand -* reusing an object is difficult because it refers to and communicates with many other objects -* a behavior that's distributed between several classes should be customizable without a lot of subclassing +* A set of objects communicate in well-defined but complex ways. The resulting interdependencies are unstructured and difficult to understand +* Reusing an object is difficult because it refers to and communicates with many other objects +* A behavior that's distributed between several classes should be customizable without a lot of subclassing -## Real world examples +## Known uses * All scheduleXXX() methods of [java.util.Timer](http://docs.oracle.com/javase/8/docs/api/java/util/Timer.html) * [java.util.concurrent.Executor#execute()](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-) diff --git a/memento/README.md b/memento/README.md index f9c8b95c7..699c4ae50 100644 --- a/memento/README.md +++ b/memento/README.md @@ -20,10 +20,10 @@ object can be restored to this state later. ## Explanation -Real world example +Real-world example -> We are working on astrology application where we need to analyze star properties over time. We are -> creating snapshots of star state using Memento pattern. +> We are working on an astrology application where we need to analyze star properties over time. We +> are creating snapshots of star states using the Memento pattern. In plain words @@ -51,7 +51,7 @@ public enum StarType { ``` Next, let's jump straight to the essentials. Here's the `Star` class along with the mementos that we -need manipulate. Especially pay attention to `getMemento` and `setMemento` methods. +need to manipulate. Especially pay attention to `getMemento` and `setMemento` methods. ```java public interface StarMemento { @@ -176,7 +176,7 @@ Use the Memento pattern when * A direct interface to obtaining the state would expose implementation details and break the object's encapsulation -## Real world examples +## Known uses * [java.util.Date](http://docs.oracle.com/javase/8/docs/api/java/util/Date.html) diff --git a/observer/README.md b/observer/README.md index 21d21b596..b87ce469d 100644 --- a/observer/README.md +++ b/observer/README.md @@ -21,10 +21,10 @@ dependents are notified and updated automatically. ## Explanation -Real world example +Real-world example -> In a land far away lives the races of hobbits and orcs. Both of them are mostly outdoors so they -> closely follow the changes in weather. One could say that they are constantly observing the +> In a land far away live the races of hobbits and orcs. Both of them are mostly outdoors so they +> closely follow the weather changes. One could say that they are constantly observing the > weather. In plain words @@ -152,11 +152,7 @@ be changed. * When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled. -## Typical Use Case - -* Changing in one object leads to a change in other objects. - -## Real world examples +## Known uses * [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) diff --git a/observer/src/main/java/com/iluwatar/observer/App.java b/observer/src/main/java/com/iluwatar/observer/App.java index f261651fe..9b2df3161 100644 --- a/observer/src/main/java/com/iluwatar/observer/App.java +++ b/observer/src/main/java/com/iluwatar/observer/App.java @@ -58,7 +58,7 @@ public class App { weather.timePasses(); weather.timePasses(); - // Generic observer inspired by Java Generics and Collection by Naftalin & Wadler + // Generic observer inspired by Java Generics and Collections by Naftalin & Wadler LOGGER.info("--Running generic version--"); var genericWeather = new GWeather(); genericWeather.addObserver(new GOrcs()); diff --git a/pom.xml b/pom.xml index df2f45317..31cf03b4d 100644 --- a/pom.xml +++ b/pom.xml @@ -105,7 +105,7 @@ facade flyweight proxy - chain + chain-of-responsibility command interpreter iterator diff --git a/prototype/README.md b/prototype/README.md index c43d60abe..d4f3ef4ef 100644 --- a/prototype/README.md +++ b/prototype/README.md @@ -17,17 +17,17 @@ copying this prototype. ## Explanation -First it should be noted that Prototype pattern is not used to gain performance benefits. It's only -used for creating new objects from prototype instance. +First, it should be noted that the Prototype pattern is not used to gain performance benefits. It's only +used for creating new objects from prototype instances. -Real world example +Real-world example > Remember Dolly? The sheep that was cloned! Lets not get into the details but the key point here is > that it is all about cloning. In plain words -> Create object based on an existing object through cloning. +> Create an object based on an existing object through cloning. Wikipedia says @@ -40,35 +40,127 @@ of going through the trouble of creating an object from scratch and setting it u **Programmatic Example** -In Java, it can be easily done by implementing `Cloneable` and overriding `clone` from `Object` +In Java, the prototype pattern is recommended to be implemented as follows. First, create an +interface with a method for cloning objects. In this example, `Prototype` interface accomplishes +this with its `copy` method. ```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; } +public interface Prototype { + Object copy(); +} +``` + +Our example contains a hierarchy of different creatures. For example, let's look at `Beast` and +`OrcBeast` classes. + +```java +@EqualsAndHashCode +@NoArgsConstructor +public abstract class Beast implements Prototype { + + public Beast(Beast source) { + } + @Override - public Sheep clone() { - try { - return (Sheep)super.clone(); - } catch(CloneNotSuportedException) { - throw new InternalError(); - } + public abstract Beast copy(); +} + +@EqualsAndHashCode(callSuper = false) +@RequiredArgsConstructor +public class OrcBeast extends Beast { + + private final String weapon; + + public OrcBeast(OrcBeast orcBeast) { + super(orcBeast); + this.weapon = orcBeast.weapon; + } + + @Override + public OrcBeast copy() { + return new OrcBeast(this); + } + + @Override + public String toString() { + return "Orcish wolf attacks with " + weapon; } } ``` -Then it can be cloned like below: +We don't want to go into too much details, but the full example contains also base classes `Mage` +and `Warlord` and there are specialized implementations for those for elves in addition to orcs. + +To take full advantage of the prototype pattern, we create `HeroFactory` and `HeroFactoryImpl` +classes to produce different kinds of creatures from prototypes. ```java -var original = new Sheep("Jolly"); -System.out.println(original.getName()); // Jolly +public interface HeroFactory { + + Mage createMage(); + Warlord createWarlord(); + Beast createBeast(); +} -// Clone and modify what is required -var cloned = original.clone(); -cloned.setName("Dolly"); -System.out.println(cloned.getName()); // Dolly +@RequiredArgsConstructor +public class HeroFactoryImpl implements HeroFactory { + + private final Mage mage; + private final Warlord warlord; + private final Beast beast; + + public Mage createMage() { + return mage.copy(); + } + + public Warlord createWarlord() { + return warlord.copy(); + } + + public Beast createBeast() { + return beast.copy(); + } +} +``` + +Now, we are able to show the full prototype pattern in action producing new creatures by cloning +existing instances. + +```java + var factory = new HeroFactoryImpl( + new ElfMage("cooking"), + new ElfWarlord("cleaning"), + new ElfBeast("protecting") + ); + var mage = factory.createMage(); + var warlord = factory.createWarlord(); + var beast = factory.createBeast(); + LOGGER.info(mage.toString()); + LOGGER.info(warlord.toString()); + LOGGER.info(beast.toString()); + + factory = new HeroFactoryImpl( + new OrcMage("axe"), + new OrcWarlord("sword"), + new OrcBeast("laser") + ); + mage = factory.createMage(); + warlord = factory.createWarlord(); + beast = factory.createBeast(); + LOGGER.info(mage.toString()); + LOGGER.info(warlord.toString()); + LOGGER.info(beast.toString()); +``` + +Here's the console output from running the example. + +``` +Elven mage helps in cooking +Elven warlord helps in cleaning +Elven eagle helps in protecting +Orcish mage attacks with axe +Orcish warlord attacks with sword +Orcish wolf attacks with laser ``` ## Class diagram @@ -87,7 +179,7 @@ more convenient to install a corresponding number of prototypes and clone them r instantiating the class manually, each time with the appropriate state. * When object creation is expensive compared to cloning. -## Real world examples +## Known uses * [java.lang.Object#clone()](http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone%28%29) diff --git a/prototype/src/main/java/com/iluwatar/prototype/App.java b/prototype/src/main/java/com/iluwatar/prototype/App.java index 998106ec9..0f2dd5f42 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/App.java +++ b/prototype/src/main/java/com/iluwatar/prototype/App.java @@ -29,7 +29,7 @@ import lombok.extern.slf4j.Slf4j; * The Prototype pattern is a creational design pattern in software development. It is used when the * type of objects to create is determined by a prototypical instance, which is cloned to produce * new objects. This pattern is used to: - avoid subclasses of an object creator in the client - * application, like the abstract factory pattern does. - avoid the inherent cost of creating a new + * application, like the abstract factory pattern, does. - avoid the inherent cost of creating a new * object in the standard way (e.g., using the 'new' keyword) * *

In this example we have a factory class ({@link HeroFactoryImpl}) producing objects by diff --git a/proxy/README.md b/proxy/README.md index a0c4b5285..7b07e2e7a 100644 --- a/proxy/README.md +++ b/proxy/README.md @@ -20,7 +20,7 @@ Provide a surrogate or placeholder for another object to control access to it. ## Explanation -Real world example +Real-world example > Imagine a tower where the local wizards go to study their spells. The ivory tower can only be > accessed through a proxy which ensures that only the first three wizards can enter. Here the proxy @@ -142,7 +142,7 @@ applicable. * Protection proxy controls access to the original object. Protection proxies are useful when objects should have different access rights. -## Typical Use Case +Typically, the proxy pattern is used to * Control access to another object * Lazy initialization diff --git a/singleton/README.md b/singleton/README.md index 5f058ffea..ffff61e15 100644 --- a/singleton/README.md +++ b/singleton/README.md @@ -13,13 +13,12 @@ tags: Ensure a class only has one instance, and provide a global point of access to it. - ## Explanation -Real world example +Real-world example > There can only be one ivory tower where the wizards study their magic. The same enchanted ivory -> tower is always used by the wizards. Ivory tower here is singleton. +> tower is always used by the wizards. The ivory tower here is a singleton. In plain words @@ -46,9 +45,17 @@ public enum EnumIvoryTower { Then in order to use: ```java -var enumIvoryTower1 = EnumIvoryTower.INSTANCE; -var enumIvoryTower2 = EnumIvoryTower.INSTANCE; -assertEquals(enumIvoryTower1, enumIvoryTower2); // true + var enumIvoryTower1 = EnumIvoryTower.INSTANCE; + var enumIvoryTower2 = EnumIvoryTower.INSTANCE; + LOGGER.info("enumIvoryTower1={}", enumIvoryTower1); + LOGGER.info("enumIvoryTower2={}", enumIvoryTower2); +``` + +The console output + +``` +enumIvoryTower1=com.iluwatar.singleton.EnumIvoryTower@1221555852 +enumIvoryTower2=com.iluwatar.singleton.EnumIvoryTower@1221555852 ``` ## Class diagram @@ -62,13 +69,13 @@ Use the Singleton pattern when * There must be exactly one instance of a class, and it must be accessible to clients from a well-known access point * When the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code -## Typical Use Case +Some typical use cases for the Singleton * The logging class * Managing a connection to a database * File manager -## Real world examples +## Known uses * [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--) @@ -77,8 +84,8 @@ Use the Singleton pattern when ## Consequences -* Violates Single Responsibility Principle (SRP) by controlling their own creation and lifecycle. -* Encourages using a global shared instance which prevents an object and resources used by this object from being deallocated. +* Violates Single Responsibility Principle (SRP) by controlling their creation and lifecycle. +* Encourages using a globally shared instance which prevents an object and resources used by this object from being deallocated. * Creates tightly coupled code. The clients of the Singleton become difficult to test. * Makes it almost impossible to subclass a Singleton. diff --git a/singleton/src/main/java/com/iluwatar/singleton/App.java b/singleton/src/main/java/com/iluwatar/singleton/App.java index 4c02262d2..b5eed98da 100644 --- a/singleton/src/main/java/com/iluwatar/singleton/App.java +++ b/singleton/src/main/java/com/iluwatar/singleton/App.java @@ -30,20 +30,20 @@ import lombok.extern.slf4j.Slf4j; * classloader instance and provides global access to it.

* *

One of the risks of this pattern is that bugs resulting from setting a singleton up in a - * distributed environment can be tricky to debug, since it will work fine if you debug with a + * distributed environment can be tricky to debug since it will work fine if you debug with a * single classloader. Additionally, these problems can crop up a while after the implementation of - * a singleton, since they may start out synchronous and only become async with time, so it may - * not be clear why you are seeing certain changes in behaviour.

+ * a singleton, since they may start synchronous and only become async with time, so it may + * not be clear why you are seeing certain changes in behavior.

* *

There are many ways to implement the Singleton. The first one is the eagerly initialized * instance in {@link IvoryTower}. Eager initialization implies that the implementation is thread - * safe. If you can afford giving up control of the instantiation moment, then this implementation + * safe. If you can afford to give up control of the instantiation moment, then this implementation * will suit you fine.

* - *

The other option to implement eagerly initialized Singleton is enum based Singleton. The - * example is found in {@link EnumIvoryTower}. At first glance the code looks short and simple. + *

The other option to implement eagerly initialized Singleton is enum-based Singleton. The + * example is found in {@link EnumIvoryTower}. At first glance, the code looks short and simple. * However, you should be aware of the downsides including committing to implementation strategy, - * extending the enum class, serializability and restrictions to coding. These are extensively + * extending the enum class, serializability, and restrictions to coding. These are extensively * discussed in Stack Overflow: http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing * -a-singleton-with-javas-enum

* @@ -56,7 +56,7 @@ import lombok.extern.slf4j.Slf4j; * ThreadSafeLazyLoadedIvoryTower} since it doesn't synchronize the whole access method but only the * method internals on specific conditions.

* - *

Yet another way to implement thread safe lazily initialized Singleton can be found in + *

Yet another way to implement thread-safe lazily initialized Singleton can be found in * {@link InitializingOnDemandHolderIdiom}. However, this implementation requires at least Java 8 * API level to work.

*/ diff --git a/state/README.md b/state/README.md index 3afddb7a5..c6f07e7b6 100644 --- a/state/README.md +++ b/state/README.md @@ -20,10 +20,10 @@ change its class. ## Explanation -Real world example +Real-world example > When observing a mammoth in its natural habitat it seems to change its behavior based on the -> situation. It may first appear calm but over time when it detects a threat it gets angry and +> situation. It may first appear calm, but over time when it detects a threat, it gets angry and > dangerous to its surroundings. In plain words @@ -125,7 +125,7 @@ public class Mammoth { } ``` -And here is the full example how the mammoth behaves over time. +Here is the full example of how the mammoth behaves over time. ```java var mammoth = new Mammoth(); @@ -156,7 +156,7 @@ Use the State pattern in either of the following cases * An object's behavior depends on its state, and it must change its behavior at run-time depending on that state * Operations have large, multipart conditional statements that depend on the object's state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure. The State pattern puts each branch of the conditional in a separate class. This lets you treat the object's state as an object in its own right that can vary independently from other objects. -## Real world examples +## Known uses * [javax.faces.lifecycle.Lifecycle#execute()](http://docs.oracle.com/javaee/7/api/javax/faces/lifecycle/Lifecycle.html#execute-javax.faces.context.FacesContext-) controlled by [FacesServlet](http://docs.oracle.com/javaee/7/api/javax/faces/webapp/FacesServlet.html), the behavior is dependent on current phase of lifecycle. * [JDiameter - Diameter State Machine](https://github.com/npathai/jdiameter/blob/master/core/jdiameter/api/src/main/java/org/jdiameter/api/app/State.java) diff --git a/state/src/main/java/com/iluwatar/state/App.java b/state/src/main/java/com/iluwatar/state/App.java index a7cd79b77..8cf17e335 100644 --- a/state/src/main/java/com/iluwatar/state/App.java +++ b/state/src/main/java/com/iluwatar/state/App.java @@ -24,7 +24,7 @@ package com.iluwatar.state; /** - * In State pattern the container object has an internal state object that defines the current + * In the State pattern, the container object has an internal state object that defines the current * behavior. The state object can be changed to alter the behavior. * *

This can be a cleaner way for an object to change its behavior at runtime without resorting diff --git a/state/src/main/java/com/iluwatar/state/State.java b/state/src/main/java/com/iluwatar/state/State.java index 2fd86df66..339f06893 100644 --- a/state/src/main/java/com/iluwatar/state/State.java +++ b/state/src/main/java/com/iluwatar/state/State.java @@ -31,5 +31,4 @@ public interface State { void onEnterState(); void observe(); - } diff --git a/strategy/README.md b/strategy/README.md index eb7bbbd01..83774fba8 100644 --- a/strategy/README.md +++ b/strategy/README.md @@ -16,18 +16,18 @@ Policy ## Intent Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets -the algorithm vary independently from clients that use it. +the algorithm vary independently from the clients that use it. ## Explanation -Real world example +Real-world example -> Slaying dragons is a dangerous job. With experience it becomes easier. Veteran +> Slaying dragons is a dangerous job. With experience, it becomes easier. Veteran > dragonslayers have developed different fighting strategies against different types of dragons. In plain words -> Strategy pattern allows choosing the best suited algorithm at runtime. +> Strategy pattern allows choosing the best-suited algorithm at runtime. Wikipedia says @@ -36,7 +36,7 @@ Wikipedia says **Programmatic Example** -Let's first introduce the dragon slaying strategy interface and its implementations. +Let's first introduce the dragon-slaying strategy interface and its implementations. ```java @FunctionalInterface @@ -73,7 +73,7 @@ public class SpellStrategy implements DragonSlayingStrategy { } ``` -And here is the mighty dragonslayer, who is able to pick his fighting strategy based on the +And here is the mighty dragonslayer, who can pick his fighting strategy based on the opponent. ```java @@ -95,7 +95,7 @@ public class DragonSlayer { } ``` -Finally here's the dragonslayer in action. +Finally, here's the dragonslayer in action. ```java LOGGER.info("Green dragon spotted ahead!"); @@ -120,7 +120,7 @@ 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: +What's more, the lambda expressions in Java 8 provides another approach for the implementation: ```java public class LambdaStrategy { @@ -163,7 +163,7 @@ And here's the dragonslayer in action. dragonSlayer.goToBattle(); ``` -Program output is the same as above one. +The program output is the same as the above one. ## Class diagram @@ -175,8 +175,8 @@ Use the Strategy pattern when * Many related classes differ only in their behavior. Strategies provide a way to configure a class either one of many behaviors * You need different variants of an algorithm. for example, you might define algorithms reflecting different space/time trade-offs. Strategies can be used when these variants are implemented as a class hierarchy of algorithms -* An algorithm uses data that clients shouldn't know about. Use the Strategy pattern to avoid exposing complex, algorithm-specific data structures -* A class defines many behaviors, and these appear as multiple conditional statements in its operations. Instead of many conditionals, move related conditional branches into their own Strategy class +* An algorithm uses data that clients shouldn't know about. Use the Strategy pattern to avoid exposing complex algorithm-specific data structures +* A class defines many behaviors, and these appear as multiple conditional statements in its operations. Instead of many conditionals, move the related conditional branches into their own Strategy class ## Tutorial diff --git a/strategy/src/main/java/com/iluwatar/strategy/App.java b/strategy/src/main/java/com/iluwatar/strategy/App.java index 8554ce3ff..383712c39 100644 --- a/strategy/src/main/java/com/iluwatar/strategy/App.java +++ b/strategy/src/main/java/com/iluwatar/strategy/App.java @@ -31,7 +31,7 @@ import lombok.extern.slf4j.Slf4j; * enables an algorithm's behavior to be selected at runtime.

* *

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

* *

In this example ({@link DragonSlayingStrategy}) encapsulates an algorithm. The containing diff --git a/template-method/README.md b/template-method/README.md index e984473a9..7209176f2 100644 --- a/template-method/README.md +++ b/template-method/README.md @@ -17,10 +17,11 @@ structure. ## Explanation -Real world example +Real-world example -> The general steps in stealing an item are the same. First you pick the target, next you confuse -> him somehow and finally you steal the item. However there are many ways to implement these steps. +> The general steps in stealing an item are the same. First, you pick the target, next you confuse +> him somehow and finally, you steal the item. However, there are many ways to implement these +> steps. In plain words @@ -117,7 +118,7 @@ public class HalflingThief { } ``` -And finally we show how the halfling thief utilizes the different stealing methods. +And finally, we show how the halfling thief utilizes the different stealing methods. ```java var thief = new HalflingThief(new HitAndRunMethod()); @@ -135,14 +136,14 @@ And finally we show how the halfling thief utilizes the different stealing metho The Template Method pattern should be used * To implement the invariant parts of an algorithm once and leave it up to subclasses to implement the behavior that can vary -* When common behavior among subclasses should be factored and localized in a common class to avoid code duplication. This is good example of "refactoring to generalize" as described by Opdyke and Johnson. You first identify the differences in the existing code and then separate the differences into new operations. Finally, you replace the differing code with a template method that calls one of these new operations +* When common behavior among subclasses should be factored and localized in a common class to avoid code duplication. This is a good example of "refactoring to generalize" as described by Opdyke and Johnson. You first identify the differences in the existing code and then separate the differences into new operations. Finally, you replace the differing code with a template method that calls one of these new operations * To control subclasses extensions. You can define a template method that calls "hook" operations at specific points, thereby permitting extensions only at those points -## Tutorial +## Tutorials * [Template-method Pattern Tutorial](https://www.journaldev.com/1763/template-method-design-pattern-in-java) -## Real world examples +## Known uses * [javax.servlet.GenericServlet.init](https://jakarta.ee/specifications/servlet/4.0/apidocs/javax/servlet/GenericServlet.html#init--): Method `GenericServlet.init(ServletConfig config)` calls the parameterless method `GenericServlet.init()` which is intended to be overridden in subclasses. diff --git a/visitor/README.md b/visitor/README.md index 538e49ab7..82176238f 100644 --- a/visitor/README.md +++ b/visitor/README.md @@ -16,11 +16,11 @@ define a new operation without changing the classes of the elements on which it ## Explanation -Real world example +Real-world example > Consider a tree structure with army units. Commander has two sergeants under it and each sergeant > has three soldiers under them. Given that the hierarchy implements the visitor pattern, we can -> easily create new objects that interact with the commander, sergeants, soldiers or all of them. +> easily create new objects that interact with the commander, sergeants, soldiers, or all of them. In plain words @@ -214,7 +214,7 @@ Use the Visitor pattern when * Many distinct and unrelated operations need to be performed on objects in an object structure, and you want to avoid "polluting" their classes with these operations. Visitor lets you keep related operations together by defining them in one class. When the object structure is shared by many applications, use Visitor to put operations in just those applications that need them. * The classes defining the object structure rarely change, but you often want to define new operations over the structure. Changing the object structure classes requires redefining the interface to all visitors, which is potentially costly. If the object structure classes change often, then it's probably better to define the operations in those classes. -## Real world examples +## Known uses * [Apache Wicket](https://github.com/apache/wicket) component tree, see [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java) * [javax.lang.model.element.AnnotationValue](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValue.html) and [AnnotationValueVisitor](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValueVisitor.html) diff --git a/visitor/src/main/java/com/iluwatar/visitor/App.java b/visitor/src/main/java/com/iluwatar/visitor/App.java index 6f4be74f5..da319b0f0 100644 --- a/visitor/src/main/java/com/iluwatar/visitor/App.java +++ b/visitor/src/main/java/com/iluwatar/visitor/App.java @@ -24,8 +24,8 @@ package com.iluwatar.visitor; /** - *

Visitor pattern defines mechanism to apply operations on nodes in hierarchy. New operations - * can be added without altering the node interface.

+ *

Visitor pattern defines a mechanism to apply operations on nodes in a hierarchy. New + * operations can be added without altering the node interface.

* *

In this example there is a unit hierarchy beginning from {@link Commander}. This hierarchy is * traversed by visitors. {@link SoldierVisitor} applies its operation on {@link Soldier}s, {@link From 28fc672a2f9d004b477f05a8b794ff00ea33492d Mon Sep 17 00:00:00 2001 From: Marlo Henrique <40809563+marlo2222@users.noreply.github.com> Date: Fri, 9 Jul 2021 04:44:06 -0300 Subject: [PATCH 06/11] translation: portuguese translation and languages codes (#1792) * portuguese translation and languages codes * fix unlinked links Co-authored-by: Marlo Henrique de Lima Oliveira --- README.md | 2 +- localization/pt/README.md | 334 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 localization/pt/README.md diff --git a/README.md b/README.md index eacced422..4e3772a6d 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@
-Read in different language : [**zh**](/localization/zh/README.md), [**ko**](/localization/ko/README.md), [**fr**](/localization/fr/README.md), [**tr**](/localization/tr/README.md), [**ar**](/localization/ar/README.md), [**es**](/localization/es/README.md) +Read in different language : [**zh**](/localization/zh/README.md), [**ko**](/localization/ko/README.md), [**fr**](/localization/fr/README.md), [**tr**](/localization/tr/README.md), [**ar**](/localization/ar/README.md), [**es**](/localization/es/README.md), [**pt**](/localization/pt/README.md)
diff --git a/localization/pt/README.md b/localization/pt/README.md new file mode 100644 index 000000000..bac027fab --- /dev/null +++ b/localization/pt/README.md @@ -0,0 +1,334 @@ + + +# Padrões de projeto implementados em Java + +![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg) +[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md) +[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns) +[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +[![All Contributors](https://img.shields.io/badge/all_contributors-170-orange.svg?style=flat-square)](#contributors-) + +
+ +Leia em outro idioma: [**zh**](/localization/zh/README.md), [**ko**](/localization/ko/README.md), [**fr**](/localization/fr/README.md), [**tr**](/localization/tr/README.md), [**ar**](/localization/ar/README.md), [**es**](/localization/es/README.md) + +
+ +# Introdução + +Os padrões de projeto são um conjunto das melhores práticas e soluções formalizadas que um programador pode usar para resolver problemas comuns ao projetar um aplicativo ou sistema. + +Os padrões de projeto podem acelerar o processo de desenvolvimento, fornecendo testes e comprovados paradigmas de desenvolvimento. + +Reutilizar padrões de projeto ajuda a evitar problemas sutis que causam +problemas, e também melhora a legibilidade do código para desenvolvedores e arquitetos que +estão familiarizados com os padrões. + +# Começando + +Este site apresenta padrões de projeto Java. As soluções foram desenvolvidas por +programadores e arquitetos experientes da comunidade de código aberto. Os +padrões podem ser acessados por meio de suas descrições de alto nível ou por meio de seu +Código fonte. Os exemplos de código-fonte são bem comentados e podem ser considerados como +tutoriais de programação sobre como implementar um padrão específico. Nós usamos as mais +populares tecnologias Java de código aberto comprovadas em batalhas. + +Antes de mergulhar no material, você deve estar familiarizado com vários +[Princípios de design de software](https://java-design-patterns.com/principles/). + +Todos os projetos devem ser o mais simples possível. Você deve começar com KISS, YAGNI, +e fazer a coisa mais simples que poderia funcionar com os princípios. Complexidade e +os padrões só devem ser introduzidos quando são necessários para fins práticos e +extensibilidade. + +Assim que estiver familiarizado com esses conceitos, você pode começar a se aprofundar nos +[padrões de projeto disponíveis](https://java-design-patterns.com/patterns/) por qualquer +das seguintes abordagens + + - Pesquise um padrão específico por nome. Não consegue encontrar um? Informe um novo padrão [aqui](https://github.com/iluwatar/java-design-patterns/issues). + - Usando tags como `Performance`,` Gang of Four` ou `Acesso de dados`. + - Usando categorias de padrões, `Criacional`,` Comportamental` e outros. + + Esperamos que você encontre as soluções orientadas a objetos apresentadas neste site úteis +em suas arquiteturas e divirta-se as aprendendo tanto quanto nos divertimos ao desenvolvê-las. + +# Como contribuir + +Se você estiver disposto a contribuir para o projeto, você encontrará as informações mais relevantes em nossa [wiki do desenvolvedor](https://github.com/iluwatar/java-design-patterns/wiki). Ajudaremos você e responderemos as suas perguntas na [sala de bate-papo do Gitter](https://gitter.im/iluwatar/java-design-patterns). + +# Licença + +Este projeto está licenciado sob os termos da licença MIT. + +# Contribuidores + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Ilkka Seppälä

📆 🚧 🖋

amit1307

💻

Narendra Pathai

💻 🤔 👀

Jeroen Meulemeester

💻

Joseph McCarthy

💻

Thomas

💻

Anurag Agarwal

💻

Markus Moser

🎨 💻 🤔

Sabiq Ihab

💻

Amit Dixit

💻

Piyush Kailash Chaudhari

💻

joshzambales

💻

Kamil Pietruszka

💻

Zafar Khaydarov

💻 📖

Paul Campbell

💻

Argyro Sioziou

💻

TylerMcConville

💻

saksham93

💻

nikhilbarar

💻

Colin But

💻

Ruslan

💻

Juho Kang

💻

Dheeraj Mummareddy

💻

Bernardo Sulzbach

💻

Aleksandar Dudukovic

💻

Yusuf Aytaş

💻

Mihály Kuprivecz

💻

Stanislav Kapinus

💻

GVSharma

💻

Srđan Paunović

💻

Petros G. Sideris

💻

Pramod Gupta

👀

Amarnath Chandana

💻

Anurag870

💻 📖

Wes Gilleland

💻

Harshraj Thakor

💻

Martin Vandenbussche

💻

Alexandru Somai

💻

Artur Mogozov

💻

anthony

💻

Christian Cygnus

💻

Dima Gubin

💻

Joshua Jimenez

💻

Kai Winter

💻

lbroman

💻

Przemek

💻

Prafful Agarwal

🖋

Sanket Panhale

🖋

staillebois

💻

Krisztián Nagy

💻

Alexander Ivanov

💻

Yosfik Alqadri

💻

Agustí Becerra Milà

💻

Juan Manuel Suárez

💻

Luigi Cortese

💻

Katarzyna Rzepecka

💻

adamski.pro

💻

Shengli Bai

💻

Boris

💻

Dmitry Avershin

💻

靳阳

💻

hoangnam2261

💻

Arpit Jain

💻

Jón Ingi Sveinbjörnsson

💻

Kirill Vlasov

💻

Mitchell Irvin

💻

Ranjeet

💻

PhoenixYip

💻

M Saif Asif

💻

kanwarpreet25

💻

Leon Mak

💻

Per Wramdemark

💻

Evan Sia Wai Suan

💻

AnaghaSasikumar

💻

Christoffer Hamberg

💻

Dominik Gruntz

💻

Hannes

💻

Leo Gutiérrez Ramírez

💻

Zhang WH

💻

Christopher O'Connell

💻

George Mavroeidis

💻

Hemant Bothra

💻 🎨

Kevin Peters

💻

George Aristy

💻

Mahendran Mookkiah

💻

Azureyjt

💻

gans

💻

Matt

🖋

Gopinath Langote

💻

Hoswey

💻

Amit Pandey

💻

gwildor28

🖋

田浩

🖋

Stamatis Pitsios

💻

qza

💻

Rodolfo Forte

🖋

Ankur Kaushal

💻

Ovidijus Okinskas

💻

Robert Kasperczyk

💻

Tapio Rautonen

💻

Yuri Orlov

💻

Varun Upadhyay

💻

Aditya Pal

💻

grzesiekkedzior

💻 👀

Sivasubramani M

💻

Sami Airaksinen

💻

Janne Sinivirta

💻

Boris-Chengbiao Zhou

🖋

Jacob Hein

🖋

Richard Jones

🖋

Rachel M. Carmena

🖋

Zaerald Denze Lungos

🖋

Lars Kappert

🖋

Mike Liu

🌍

Matt Dolan

💻 👀

Manan

👀

Nishant Arora

💻

Peeyush

💻

Rakesh

💻 👀

Wei Seng

💻

Ashish Trivedi

💻

洪月阳

💻

xdvrx1

👀 🤔

Subhrodip Mohanta

💻 👀 🚧

Bethan Palmer

💻

Toxic Dreamz

💻

Edy Cu Tjong

📖

Michał Krzywański

💻

Stefan Birkner

💻

Fedor Skvorcov

💻

samilAyoub

💻

Vladislav Golubinov

💻

Swaraj

💻

Christoph Flick

📖

Ascênio

👀

Domenico Sibilio

📖

Akash Chandwani

👀

Pavlo Manannikov

💻

Eiman

💻

Rocky

📖

Ibrahim ali abdelghany

👀

Girish Kulkarni

📖

Omar Karazoun

💻

Jeff Evans

💻

Vivek Singh

💻

siavash

💻

ruchpeanuts

📖

warp125

🌍

KHADIR Tayeb

🌍

ignite1771

💻

Halil Demir

🌍

Rohit Singh

💻

byoungju94

💻

Moustafa Farhat

🌍

Martel Richard

💻

va1m

💻

Noam Greenshtain

💻

yonghong Xu

📖

jinishavora

👀 💻

Elvys Soares

💻

zWeBrain

💻

余林颖

🌍

Alain

🌍

VR

📖

JackieNim

💻

EdisonE3

💻

Tao

💻

Juan Manuel Abate

🌍

Xenilo137

💻

Samuel Souza

💻
+ + + + + From eaeb6e717cd042b4f8f9777724620d1e9f961071 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 9 Jul 2021 10:47:34 +0300 Subject: [PATCH 07/11] docs: add marlo2222 as a contributor for translation (#1798) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 798cd6a90..6fa850e92 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1550,6 +1550,15 @@ "contributions": [ "code" ] + }, + { + "login": "marlo2222", + "name": "Marlo Henrique", + "avatar_url": "https://avatars.githubusercontent.com/u/40809563?v=4", + "profile": "https://github.com/marlo2222", + "contributions": [ + "translation" + ] } ], "contributorsPerLine": 4, diff --git a/README.md b/README.md index 4e3772a6d..5dd071fa1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns) [![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![All Contributors](https://img.shields.io/badge/all_contributors-170-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-171-orange.svg?style=flat-square)](#contributors-)
@@ -330,6 +330,7 @@ This project is licensed under the terms of the MIT license.
Xenilo137

💻
Samuel Souza

💻 +
Marlo Henrique

🌍 From eac85678f0888b333fa3e1909a37a04bff353a32 Mon Sep 17 00:00:00 2001 From: AndriyPyzh <57706635+AndriyPyzh@users.noreply.github.com> Date: Thu, 22 Jul 2021 16:58:21 +0300 Subject: [PATCH 08/11] feature: Added Domain Model pattern (#1795) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * domain-model pattern * fixed optional get before check isPresent * readme minor changes * change currency representation with joda money * changed names of test methods * fixed code smells * Update domain-model/README.md Co-authored-by: Ilkka Seppälä * Update domain-model/README.md Co-authored-by: Ilkka Seppälä * updated readme and diagrams Co-authored-by: Ilkka Seppälä --- domain-model/README.md | 322 ++++++++++++++++++ domain-model/etc/domain-model.urm.png | Bin 0 -> 321538 bytes domain-model/etc/domain-model.urm.puml | 87 +++++ domain-model/pom.xml | 78 +++++ .../java/com/iluwatar/domainmodel/App.java | 173 ++++++++++ .../com/iluwatar/domainmodel/Customer.java | 153 +++++++++ .../com/iluwatar/domainmodel/CustomerDao.java | 40 +++ .../iluwatar/domainmodel/CustomerDaoImpl.java | 109 ++++++ .../com/iluwatar/domainmodel/Product.java | 94 +++++ .../com/iluwatar/domainmodel/ProductDao.java | 36 ++ .../iluwatar/domainmodel/ProductDaoImpl.java | 92 +++++ .../com/iluwatar/domainmodel/AppTest.java | 38 +++ .../domainmodel/CustomerDaoImplTest.java | 164 +++++++++ .../iluwatar/domainmodel/CustomerTest.java | 112 ++++++ .../domainmodel/ProductDaoImplTest.java | 127 +++++++ .../com/iluwatar/domainmodel/ProductTest.java | 78 +++++ .../com/iluwatar/domainmodel/TestUtils.java | 53 +++ pom.xml | 13 +- strategy/pom.xml | 2 +- table-module/README.md | 2 +- 20 files changed, 1765 insertions(+), 8 deletions(-) create mode 100644 domain-model/README.md create mode 100644 domain-model/etc/domain-model.urm.png create mode 100644 domain-model/etc/domain-model.urm.puml create mode 100644 domain-model/pom.xml create mode 100644 domain-model/src/main/java/com/iluwatar/domainmodel/App.java create mode 100644 domain-model/src/main/java/com/iluwatar/domainmodel/Customer.java create mode 100644 domain-model/src/main/java/com/iluwatar/domainmodel/CustomerDao.java create mode 100644 domain-model/src/main/java/com/iluwatar/domainmodel/CustomerDaoImpl.java create mode 100644 domain-model/src/main/java/com/iluwatar/domainmodel/Product.java create mode 100644 domain-model/src/main/java/com/iluwatar/domainmodel/ProductDao.java create mode 100644 domain-model/src/main/java/com/iluwatar/domainmodel/ProductDaoImpl.java create mode 100644 domain-model/src/test/java/com/iluwatar/domainmodel/AppTest.java create mode 100644 domain-model/src/test/java/com/iluwatar/domainmodel/CustomerDaoImplTest.java create mode 100644 domain-model/src/test/java/com/iluwatar/domainmodel/CustomerTest.java create mode 100644 domain-model/src/test/java/com/iluwatar/domainmodel/ProductDaoImplTest.java create mode 100644 domain-model/src/test/java/com/iluwatar/domainmodel/ProductTest.java create mode 100644 domain-model/src/test/java/com/iluwatar/domainmodel/TestUtils.java diff --git a/domain-model/README.md b/domain-model/README.md new file mode 100644 index 000000000..89cefee80 --- /dev/null +++ b/domain-model/README.md @@ -0,0 +1,322 @@ +--- +layout: pattern +title: Domain Model +folder: domain-model +permalink: /patterns/domain-model/ +categories: Architectural +tags: + - Domain +--- +## Intent +Domain model pattern provides an object-oriented way of dealing with complicated logic. Instead of having one procedure that handles all business logic for a user action there are multiple objects and each of them handles a slice of domain logic that is relevant to it. +## Explanation + +Real world example + +> Let's assume that we need to build an e-commerce web application. While analyzing requirements you will notice that there are few nouns you talk about repeatedly. It’s your Customer, and a Product the customer looks for. These two are your domain-specific classes and each of that classes will include some business logic specific to its domain. + +In plain words + +> The Domain Model is an object model of the domain that incorporates both behavior and data. + +Programmatic Example + +In the example of the e-commerce app, we need to deal with the domain logic of customers who want to buy products and return them if they want. We can use the domain model pattern and create classes `Customer` and `Product` where every single instance of that class incorporates both behavior and data and represents only one record in the underlying table. + +Here is the `Product` domain class with fields `name`, `price`, `expirationDate` which is specific for each product, `productDao` for working with DB, `save` method for saving product and `getSalePrice` method which return price for this product with discount. + +```java +@Slf4j +@Getter +@Setter +@Builder +@AllArgsConstructor +public class Product { + + private static final int DAYS_UNTIL_EXPIRATION_WHEN_DISCOUNT_ACTIVE = 4; + private static final double DISCOUNT_RATE = 0.2; + + @NonNull private final ProductDao productDao; + @NonNull private String name; + @NonNull private Money price; + @NonNull private LocalDate expirationDate; + + /** + * Save product or update if product already exist. + */ + public void save() { + try { + Optional product = productDao.findByName(name); + if (product.isPresent()) { + productDao.update(this); + } else { + productDao.save(this); + } + } catch (SQLException ex) { + LOGGER.error(ex.getMessage()); + } + } + + /** + * Calculate sale price of product with discount. + */ + public Money getSalePrice() { + return price.minus(calculateDiscount()); + } + + private Money calculateDiscount() { + if (ChronoUnit.DAYS.between(LocalDate.now(), expirationDate) + < DAYS_UNTIL_EXPIRATION_WHEN_DISCOUNT_ACTIVE) { + + return price.multipliedBy(DISCOUNT_RATE, RoundingMode.DOWN); + } + + return Money.zero(USD); + } +} +``` + +Here is the `Customer` domain class with fields `name`, `money` which is specific for each customer, `customerDao` for working with DB, `save` for saving customer, `buyProduct` which add a product to purchases and withdraw money, `returnProduct` which remove product from purchases and return money, `showPurchases` and `showBalance` methods for printing customer's purchases and money balance. + +```java +@Slf4j +@Getter +@Setter +@Builder +public class Customer { + + @NonNull private final CustomerDao customerDao; + @Builder.Default private List purchases = new ArrayList<>(); + @NonNull private String name; + @NonNull private Money money; + + /** + * Save customer or update if customer already exist. + */ + public void save() { + try { + Optional customer = customerDao.findByName(name); + if (customer.isPresent()) { + customerDao.update(this); + } else { + customerDao.save(this); + } + } catch (SQLException ex) { + LOGGER.error(ex.getMessage()); + } + } + + /** + * Add product to purchases, save to db and withdraw money. + * + * @param product to buy. + */ + public void buyProduct(Product product) { + LOGGER.info( + String.format( + "%s want to buy %s($%.2f)...", + name, product.getName(), product.getSalePrice().getAmount())); + try { + withdraw(product.getSalePrice()); + } catch (IllegalArgumentException ex) { + LOGGER.error(ex.getMessage()); + return; + } + try { + customerDao.addProduct(product, this); + purchases.add(product); + LOGGER.info(String.format("%s bought %s!", name, product.getName())); + } catch (SQLException exception) { + receiveMoney(product.getSalePrice()); + LOGGER.error(exception.getMessage()); + } + } + + /** + * Remove product from purchases, delete from db and return money. + * + * @param product to return. + */ + public void returnProduct(Product product) { + LOGGER.info( + String.format( + "%s want to return %s($%.2f)...", + name, product.getName(), product.getSalePrice().getAmount())); + if (purchases.contains(product)) { + try { + customerDao.deleteProduct(product, this); + purchases.remove(product); + receiveMoney(product.getSalePrice()); + LOGGER.info(String.format("%s returned %s!", name, product.getName())); + } catch (SQLException ex) { + LOGGER.error(ex.getMessage()); + } + } else { + LOGGER.error(String.format("%s didn't buy %s...", name, product.getName())); + } + } + + /** + * Print customer's purchases. + */ + public void showPurchases() { + Optional purchasesToShow = + purchases.stream() + .map(p -> p.getName() + " - $" + p.getSalePrice().getAmount()) + .reduce((p1, p2) -> p1 + ", " + p2); + + if (purchasesToShow.isPresent()) { + LOGGER.info(name + " bought: " + purchasesToShow.get()); + } else { + LOGGER.info(name + " didn't bought anything"); + } + } + + /** + * Print customer's money balance. + */ + public void showBalance() { + LOGGER.info(name + " balance: " + money); + } + + private void withdraw(Money amount) throws IllegalArgumentException { + if (money.compareTo(amount) < 0) { + throw new IllegalArgumentException("Not enough money!"); + } + money = money.minus(amount); + } + + private void receiveMoney(Money amount) { + money = money.plus(amount); + } +} +``` + +In the class `App`, we create a new instance of class Customer which represents customer Tom and handle data and actions of that customer and creating three products that Tom wants to buy. + + +```java +// Create data source and create the customers, products and purchases tables +final var dataSource = createDataSource(); +deleteSchema(dataSource); +createSchema(dataSource); + +// create customer +var customerDao = new CustomerDaoImpl(dataSource); + +var tom = + Customer.builder() + .name("Tom") + .money(Money.of(USD, 30)) + .customerDao(customerDao) + .build(); + +tom.save(); + +// create products +var productDao = new ProductDaoImpl(dataSource); + +var eggs = + Product.builder() + .name("Eggs") + .price(Money.of(USD, 10.0)) + .expirationDate(LocalDate.now().plusDays(7)) + .productDao(productDao) + .build(); + +var butter = + Product.builder() + .name("Butter") + .price(Money.of(USD, 20.00)) + .expirationDate(LocalDate.now().plusDays(9)) + .productDao(productDao) + .build(); + +var cheese = + Product.builder() + .name("Cheese") + .price(Money.of(USD, 25.0)) + .expirationDate(LocalDate.now().plusDays(2)) + .productDao(productDao) + .build(); + +eggs.save(); +butter.save(); +cheese.save(); + +// show money balance of customer after each purchase +tom.showBalance(); +tom.showPurchases(); + +// buy eggs +tom.buyProduct(eggs); +tom.showBalance(); + +// buy butter +tom.buyProduct(butter); +tom.showBalance(); + +// trying to buy cheese, but receive a refusal +// because he didn't have enough money +tom.buyProduct(cheese); +tom.showBalance(); + +// return butter and get money back +tom.returnProduct(butter); +tom.showBalance(); + +// Tom can buy cheese now because he has enough money +// and there is a discount on cheese because it expires in 2 days +tom.buyProduct(cheese); + +tom.save(); + +// show money balance and purchases after shopping +tom.showBalance(); +tom.showPurchases(); +``` + +The program output: + +```java +17:52:28.690 [main] INFO com.iluwatar.domainmodel.Customer - Tom balance: USD 30.00 +17:52:28.695 [main] INFO com.iluwatar.domainmodel.Customer - Tom didn't bought anything +17:52:28.699 [main] INFO com.iluwatar.domainmodel.Customer - Tom want to buy Eggs($10.00)... +17:52:28.705 [main] INFO com.iluwatar.domainmodel.Customer - Tom bought Eggs! +17:52:28.705 [main] INFO com.iluwatar.domainmodel.Customer - Tom balance: USD 20.00 +17:52:28.705 [main] INFO com.iluwatar.domainmodel.Customer - Tom want to buy Butter($20.00)... +17:52:28.712 [main] INFO com.iluwatar.domainmodel.Customer - Tom bought Butter! +17:52:28.712 [main] INFO com.iluwatar.domainmodel.Customer - Tom balance: USD 0.00 +17:52:28.712 [main] INFO com.iluwatar.domainmodel.Customer - Tom want to buy Cheese($20.00)... +17:52:28.712 [main] ERROR com.iluwatar.domainmodel.Customer - Not enough money! +17:52:28.712 [main] INFO com.iluwatar.domainmodel.Customer - Tom balance: USD 0.00 +17:52:28.712 [main] INFO com.iluwatar.domainmodel.Customer - Tom want to return Butter($20.00)... +17:52:28.721 [main] INFO com.iluwatar.domainmodel.Customer - Tom returned Butter! +17:52:28.721 [main] INFO com.iluwatar.domainmodel.Customer - Tom balance: USD 20.00 +17:52:28.721 [main] INFO com.iluwatar.domainmodel.Customer - Tom want to buy Cheese($20.00)... +17:52:28.726 [main] INFO com.iluwatar.domainmodel.Customer - Tom bought Cheese! +17:52:28.737 [main] INFO com.iluwatar.domainmodel.Customer - Tom balance: USD 0.00 +17:52:28.738 [main] INFO com.iluwatar.domainmodel.Customer - Tom bought: Eggs - $10.00, Cheese - $20.00 +``` + +## Class diagram + +![](./etc/domain-model.urm.png "domain model") + +## Applicability + +Use a Domain model pattern when your domain logic is complex and that complexity can rapidly grow because this pattern handles increasing complexity very well. Otherwise, it's a more complex solution for organizing domain logic, so shouldn't use Domain Model pattern for systems with simple domain logic, because the cost of understanding it and complexity of data source exceeds the benefit of this pattern. + +## Related patterns + +- [Transaction Script](https://java-design-patterns.com/patterns/transaction-script/) + +- [Table Module](https://java-design-patterns.com/patterns/table-module/) + +- [Service Layer](https://java-design-patterns.com/patterns/service-layer/) + +## Credits + +* [Domain Model Pattern](https://martinfowler.com/eaaCatalog/domainModel.html) +* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0321127420&linkId=18acc13ba60d66690009505577c45c04) +* [Architecture patterns: domain model and friends](https://inviqa.com/blog/architecture-patterns-domain-model-and-friends) diff --git a/domain-model/etc/domain-model.urm.png b/domain-model/etc/domain-model.urm.png new file mode 100644 index 0000000000000000000000000000000000000000..9ba7e0ca484a02707023f107e76c08ea117c0862 GIT binary patch literal 321538 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 } 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

j~QvUnX7zjs?00>mf&72sQD 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

T=9=?|yudhCfGDO{l#}+E@QLc|kU@_bB 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

    cR1|bSX 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

    XAI9KT<}P8 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

    ?bCL`;a4+PA)(uMl1U^v&#ReSW&#+EOv1fREa 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 + ~ Customer(customerDao : CustomerDao, purchases : List, name : String, money : Money) + + builder() : CustomerBuilder {static} + + buyProduct(product : Product) + + getCustomerDao() : CustomerDao + + getMoney() : Money + + getName() : String + + getPurchases() : List + - receiveMoney(amount : Money) + + returnProduct(product : Product) + + save() + + setMoney(money : Money) + + setName(name : String) + + setPurchases(purchases : List) + + showBalance() + + showPurchases() + - withdraw(amount : Money) + } + interface CustomerDao { + + addProduct(Product, Customer) {abstract} + + deleteProduct(Product, Customer) {abstract} + + findByName(String) : Optional {abstract} + + save(Customer) {abstract} + + update(Customer) {abstract} + } + class CustomerDaoImpl { + - dataSource : DataSource + + CustomerDaoImpl(userDataSource : DataSource) + + addProduct(product : Product, customer : Customer) + + deleteProduct(product : Product, customer : Customer) + + findByName(name : String) : Optional + + save(customer : Customer) + + update(customer : Customer) + } + class Product { + - expirationDate : LocalDate + - name : String + - price : Money + - productDao : ProductDao + + Product(productDao : ProductDao, name : String, price : Money, expirationDate : LocalDate) + + builder() : ProductBuilder {static} + - calculateDiscount() : Money + + getExpirationDate() : LocalDate + + getName() : String + + getPrice() : Money + + getProductDao() : ProductDao + + getSalePrice() : Money + + save() + + setExpirationDate(expirationDate : LocalDate) + + setName(name : String) + + setPrice(price : Money) + } + interface ProductDao { + + findByName(String) : Optional {abstract} + + save(Product) {abstract} + + update(Product) {abstract} + } + class ProductDaoImpl { + - dataSource : DataSource + + ProductDaoImpl(userDataSource : DataSource) + + findByName(name : String) : Optional + + save(product : Product) + + update(product : Product) + } +} +Product --> ProductDao +Customer --> CustomerDao +Customer --> Product +CustomerDaoImpl ..|> CustomerDao +ProductDaoImpl ..|> ProductDao +@enduml \ No newline at end of file diff --git a/domain-model/pom.xml b/domain-model/pom.xml new file mode 100644 index 000000000..97b2694b6 --- /dev/null +++ b/domain-model/pom.xml @@ -0,0 +1,78 @@ + + + + + java-design-patterns + com.iluwatar + 1.25.0-SNAPSHOT + + 4.0.0 + + domain-model + + + + com.h2database + h2 + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.mockito + mockito-core + + + org.joda + joda-money + 1.0.1 + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.domainmodel.App + + + + + + + + + + \ No newline at end of file diff --git a/domain-model/src/main/java/com/iluwatar/domainmodel/App.java b/domain-model/src/main/java/com/iluwatar/domainmodel/App.java new file mode 100644 index 000000000..09d08344e --- /dev/null +++ b/domain-model/src/main/java/com/iluwatar/domainmodel/App.java @@ -0,0 +1,173 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import static org.joda.money.CurrencyUnit.USD; + +import java.sql.SQLException; +import java.time.LocalDate; +import javax.sql.DataSource; + +import org.h2.jdbcx.JdbcDataSource; +import org.joda.money.Money; + + +/** + * Domain Model pattern is a more complex solution for organizing domain logic than Transaction + * Script and Table Module. It provides an object-oriented way of dealing with complicated logic. + * Instead of having one procedure that handles all business logic for a user action like + * Transaction Script there are multiple objects and each of them handles a slice of domain logic + * that is relevant to it. The significant difference between Domain Model and Table Module pattern + * is that in Table Module a single class encapsulates all the domain logic for all records stored + * in table when in Domain Model every single class represents only one record in underlying table. + * + *

    In this example, we will use the Domain Model pattern to implement buying of products + * by customers in a Shop. The main method will create a customer and a few products. + * Customer will do a few purchases, try to buy product which are too expensive for him, + * return product which he bought to return money.

    + */ +public class App { + + public static final String H2_DB_URL = "jdbc:h2:~/test"; + + public static final String CREATE_SCHEMA_SQL = + "CREATE TABLE CUSTOMERS (name varchar primary key, money decimal);" + + "CREATE TABLE PRODUCTS (name varchar primary key, price decimal, expiration_date date);" + + "CREATE TABLE PURCHASES (" + + "product_name varchar references PRODUCTS(name)," + + "customer_name varchar references CUSTOMERS(name));"; + + public static final String DELETE_SCHEMA_SQL = + "DROP TABLE CUSTOMERS IF EXISTS;" + + "DROP TABLE PURCHASES IF EXISTS;" + + "DROP TABLE PRODUCTS IF EXISTS;"; + + /** + * Program entry point. + * + * @param args command line arguments + * @throws Exception if any error occurs + */ + public static void main(String[] args) throws Exception { + + // Create data source and create the customers, products and purchases tables + final var dataSource = createDataSource(); + deleteSchema(dataSource); + createSchema(dataSource); + + // create customer + var customerDao = new CustomerDaoImpl(dataSource); + + var tom = + Customer.builder() + .name("Tom") + .money(Money.of(USD, 30)) + .customerDao(customerDao) + .build(); + + tom.save(); + + // create products + var productDao = new ProductDaoImpl(dataSource); + + var eggs = + Product.builder() + .name("Eggs") + .price(Money.of(USD, 10.0)) + .expirationDate(LocalDate.now().plusDays(7)) + .productDao(productDao) + .build(); + + var butter = + Product.builder() + .name("Butter") + .price(Money.of(USD, 20.00)) + .expirationDate(LocalDate.now().plusDays(9)) + .productDao(productDao) + .build(); + + var cheese = + Product.builder() + .name("Cheese") + .price(Money.of(USD, 25.0)) + .expirationDate(LocalDate.now().plusDays(2)) + .productDao(productDao) + .build(); + + eggs.save(); + butter.save(); + cheese.save(); + + // show money balance of customer after each purchase + tom.showBalance(); + tom.showPurchases(); + + // buy eggs + tom.buyProduct(eggs); + tom.showBalance(); + + // buy butter + tom.buyProduct(butter); + tom.showBalance(); + + // trying to buy cheese, but receive a refusal + // because he didn't have enough money + tom.buyProduct(cheese); + tom.showBalance(); + + // return butter and get money back + tom.returnProduct(butter); + tom.showBalance(); + + // Tom can buy cheese now because he has enough money + // and there is a discount on cheese because it expires in 2 days + tom.buyProduct(cheese); + + tom.save(); + + // show money balance and purchases after shopping + tom.showBalance(); + tom.showPurchases(); + } + + private static DataSource createDataSource() { + var dataSource = new JdbcDataSource(); + dataSource.setUrl(H2_DB_URL); + return dataSource; + } + + private static void deleteSchema(DataSource dataSource) throws SQLException { + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement()) { + statement.execute(DELETE_SCHEMA_SQL); + } + } + + private static void createSchema(DataSource dataSource) throws SQLException { + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement()) { + statement.execute(CREATE_SCHEMA_SQL); + } + } +} diff --git a/domain-model/src/main/java/com/iluwatar/domainmodel/Customer.java b/domain-model/src/main/java/com/iluwatar/domainmodel/Customer.java new file mode 100644 index 000000000..4f6ecb0dd --- /dev/null +++ b/domain-model/src/main/java/com/iluwatar/domainmodel/Customer.java @@ -0,0 +1,153 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.joda.money.Money; + +/** + * This class organizes domain logic of customer. + * A single instance of this class + * contains both the data and behavior of a single customer. + */ +@Slf4j +@Getter +@Setter +@Builder +public class Customer { + + @NonNull private final CustomerDao customerDao; + @Builder.Default private List purchases = new ArrayList<>(); + @NonNull private String name; + @NonNull private Money money; + + /** + * Save customer or update if customer already exist. + */ + public void save() { + try { + Optional customer = customerDao.findByName(name); + if (customer.isPresent()) { + customerDao.update(this); + } else { + customerDao.save(this); + } + } catch (SQLException ex) { + LOGGER.error(ex.getMessage()); + } + } + + /** + * Add product to purchases, save to db and withdraw money. + * + * @param product to buy. + */ + public void buyProduct(Product product) { + LOGGER.info( + String.format( + "%s want to buy %s($%.2f)...", + name, product.getName(), product.getSalePrice().getAmount())); + try { + withdraw(product.getSalePrice()); + } catch (IllegalArgumentException ex) { + LOGGER.error(ex.getMessage()); + return; + } + try { + customerDao.addProduct(product, this); + purchases.add(product); + LOGGER.info(String.format("%s bought %s!", name, product.getName())); + } catch (SQLException exception) { + receiveMoney(product.getSalePrice()); + LOGGER.error(exception.getMessage()); + } + } + + /** + * Remove product from purchases, delete from db and return money. + * + * @param product to return. + */ + public void returnProduct(Product product) { + LOGGER.info( + String.format( + "%s want to return %s($%.2f)...", + name, product.getName(), product.getSalePrice().getAmount())); + if (purchases.contains(product)) { + try { + customerDao.deleteProduct(product, this); + purchases.remove(product); + receiveMoney(product.getSalePrice()); + LOGGER.info(String.format("%s returned %s!", name, product.getName())); + } catch (SQLException ex) { + LOGGER.error(ex.getMessage()); + } + } else { + LOGGER.error(String.format("%s didn't buy %s...", name, product.getName())); + } + } + + /** + * Print customer's purchases. + */ + public void showPurchases() { + Optional purchasesToShow = + purchases.stream() + .map(p -> p.getName() + " - $" + p.getSalePrice().getAmount()) + .reduce((p1, p2) -> p1 + ", " + p2); + + if (purchasesToShow.isPresent()) { + LOGGER.info(name + " bought: " + purchasesToShow.get()); + } else { + LOGGER.info(name + " didn't bought anything"); + } + } + + /** + * Print customer's money balance. + */ + public void showBalance() { + LOGGER.info(name + " balance: " + money); + } + + private void withdraw(Money amount) throws IllegalArgumentException { + if (money.compareTo(amount) < 0) { + throw new IllegalArgumentException("Not enough money!"); + } + money = money.minus(amount); + } + + private void receiveMoney(Money amount) { + money = money.plus(amount); + } +} diff --git a/domain-model/src/main/java/com/iluwatar/domainmodel/CustomerDao.java b/domain-model/src/main/java/com/iluwatar/domainmodel/CustomerDao.java new file mode 100644 index 000000000..eda8539e8 --- /dev/null +++ b/domain-model/src/main/java/com/iluwatar/domainmodel/CustomerDao.java @@ -0,0 +1,40 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import java.sql.SQLException; +import java.util.Optional; + +public interface CustomerDao { + + Optional findByName(String name) throws SQLException; + + void update(Customer customer) throws SQLException; + + void save(Customer customer) throws SQLException; + + void addProduct(Product product, Customer customer) throws SQLException; + + void deleteProduct(Product product, Customer customer) throws SQLException; +} diff --git a/domain-model/src/main/java/com/iluwatar/domainmodel/CustomerDaoImpl.java b/domain-model/src/main/java/com/iluwatar/domainmodel/CustomerDaoImpl.java new file mode 100644 index 000000000..e8acb3af2 --- /dev/null +++ b/domain-model/src/main/java/com/iluwatar/domainmodel/CustomerDaoImpl.java @@ -0,0 +1,109 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import static org.joda.money.CurrencyUnit.USD; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Optional; +import javax.sql.DataSource; + +import org.joda.money.Money; + +public class CustomerDaoImpl implements CustomerDao { + + private final DataSource dataSource; + + public CustomerDaoImpl(final DataSource userDataSource) { + this.dataSource = userDataSource; + } + + @Override + public Optional findByName(String name) throws SQLException { + var sql = "select * from CUSTOMERS where name = ?;"; + + try (var connection = dataSource.getConnection(); + var preparedStatement = connection.prepareStatement(sql)) { + preparedStatement.setString(1, name); + + ResultSet rs = preparedStatement.executeQuery(); + + if (rs.next()) { + return Optional.of( + Customer.builder() + .name(rs.getString("name")) + .money(Money.of(USD, rs.getBigDecimal("money"))) + .customerDao(this) + .build()); + } else { + return Optional.empty(); + } + } + } + + @Override + public void update(Customer customer) throws SQLException { + var sql = "update CUSTOMERS set money = ? where name = ?;"; + try (var connection = dataSource.getConnection(); + var preparedStatement = connection.prepareStatement(sql)) { + preparedStatement.setBigDecimal(1, customer.getMoney().getAmount()); + preparedStatement.setString(2, customer.getName()); + preparedStatement.executeUpdate(); + } + } + + @Override + public void save(Customer customer) throws SQLException { + var sql = "insert into CUSTOMERS (name, money) values (?, ?)"; + try (var connection = dataSource.getConnection(); + var preparedStatement = connection.prepareStatement(sql)) { + preparedStatement.setString(1, customer.getName()); + preparedStatement.setBigDecimal(2, customer.getMoney().getAmount()); + preparedStatement.executeUpdate(); + } + } + + @Override + public void addProduct(Product product, Customer customer) throws SQLException { + var sql = "insert into PURCHASES (product_name, customer_name) values (?,?)"; + try (var connection = dataSource.getConnection(); + var preparedStatement = connection.prepareStatement(sql)) { + preparedStatement.setString(1, product.getName()); + preparedStatement.setString(2, customer.getName()); + preparedStatement.executeUpdate(); + } + } + + @Override + public void deleteProduct(Product product, Customer customer) throws SQLException { + var sql = "delete from PURCHASES where product_name = ? and customer_name = ?"; + try (var connection = dataSource.getConnection(); + var preparedStatement = connection.prepareStatement(sql)) { + preparedStatement.setString(1, product.getName()); + preparedStatement.setString(2, customer.getName()); + preparedStatement.executeUpdate(); + } + } +} diff --git a/domain-model/src/main/java/com/iluwatar/domainmodel/Product.java b/domain-model/src/main/java/com/iluwatar/domainmodel/Product.java new file mode 100644 index 000000000..fc853e49c --- /dev/null +++ b/domain-model/src/main/java/com/iluwatar/domainmodel/Product.java @@ -0,0 +1,94 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import static org.joda.money.CurrencyUnit.USD; + +import java.math.RoundingMode; +import java.sql.SQLException; +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; +import java.util.Optional; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.joda.money.Money; + +/** + * This class organizes domain logic of product. + * A single instance of this class + * contains both the data and behavior of a single product. + */ +@Slf4j +@Getter +@Setter +@Builder +@AllArgsConstructor +public class Product { + + private static final int DAYS_UNTIL_EXPIRATION_WHEN_DISCOUNT_ACTIVE = 4; + private static final double DISCOUNT_RATE = 0.2; + + @NonNull private final ProductDao productDao; + @NonNull private String name; + @NonNull private Money price; + @NonNull private LocalDate expirationDate; + + /** + * Save product or update if product already exist. + */ + public void save() { + try { + Optional product = productDao.findByName(name); + if (product.isPresent()) { + productDao.update(this); + } else { + productDao.save(this); + } + } catch (SQLException ex) { + LOGGER.error(ex.getMessage()); + } + } + + /** + * Calculate sale price of product with discount. + */ + public Money getSalePrice() { + return price.minus(calculateDiscount()); + } + + private Money calculateDiscount() { + if (ChronoUnit.DAYS.between(LocalDate.now(), expirationDate) + < DAYS_UNTIL_EXPIRATION_WHEN_DISCOUNT_ACTIVE) { + + return price.multipliedBy(DISCOUNT_RATE, RoundingMode.DOWN); + } + + return Money.zero(USD); + } +} diff --git a/domain-model/src/main/java/com/iluwatar/domainmodel/ProductDao.java b/domain-model/src/main/java/com/iluwatar/domainmodel/ProductDao.java new file mode 100644 index 000000000..b36af2597 --- /dev/null +++ b/domain-model/src/main/java/com/iluwatar/domainmodel/ProductDao.java @@ -0,0 +1,36 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import java.sql.SQLException; +import java.util.Optional; + +public interface ProductDao { + + Optional findByName(String name) throws SQLException; + + void save(Product product) throws SQLException; + + void update(Product product) throws SQLException; +} diff --git a/domain-model/src/main/java/com/iluwatar/domainmodel/ProductDaoImpl.java b/domain-model/src/main/java/com/iluwatar/domainmodel/ProductDaoImpl.java new file mode 100644 index 000000000..e3cc70b26 --- /dev/null +++ b/domain-model/src/main/java/com/iluwatar/domainmodel/ProductDaoImpl.java @@ -0,0 +1,92 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import static org.joda.money.CurrencyUnit.USD; + +import java.sql.Date; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Optional; +import javax.sql.DataSource; + +import org.joda.money.Money; + + +public class ProductDaoImpl implements ProductDao { + + private final DataSource dataSource; + + public ProductDaoImpl(final DataSource userDataSource) { + this.dataSource = userDataSource; + } + + @Override + public Optional findByName(String name) throws SQLException { + var sql = "select * from PRODUCTS where name = ?;"; + + try (var connection = dataSource.getConnection(); + var preparedStatement = connection.prepareStatement(sql)) { + preparedStatement.setString(1, name); + + ResultSet rs = preparedStatement.executeQuery(); + + if (rs.next()) { + return Optional.of( + Product.builder() + .name(rs.getString("name")) + .price(Money.of(USD, rs.getBigDecimal("price"))) + .expirationDate(rs.getDate("expiration_date").toLocalDate()) + .productDao(this) + .build()); + } else { + return Optional.empty(); + } + } + } + + @Override + public void save(Product product) throws SQLException { + var sql = "insert into PRODUCTS (name, price, expiration_date) values (?, ?, ?)"; + try (var connection = dataSource.getConnection(); + var preparedStatement = connection.prepareStatement(sql)) { + preparedStatement.setString(1, product.getName()); + preparedStatement.setBigDecimal(2, product.getPrice().getAmount()); + preparedStatement.setDate(3, Date.valueOf(product.getExpirationDate())); + preparedStatement.executeUpdate(); + } + } + + @Override + public void update(Product product) throws SQLException { + var sql = "update PRODUCTS set price = ?, expiration_date = ? where name = ?;"; + try (var connection = dataSource.getConnection(); + var preparedStatement = connection.prepareStatement(sql)) { + preparedStatement.setBigDecimal(1, product.getPrice().getAmount()); + preparedStatement.setDate(2, Date.valueOf(product.getExpirationDate())); + preparedStatement.setString(3, product.getName()); + preparedStatement.executeUpdate(); + } + } +} diff --git a/domain-model/src/test/java/com/iluwatar/domainmodel/AppTest.java b/domain-model/src/test/java/com/iluwatar/domainmodel/AppTest.java new file mode 100644 index 000000000..eb779c585 --- /dev/null +++ b/domain-model/src/test/java/com/iluwatar/domainmodel/AppTest.java @@ -0,0 +1,38 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +/** Tests that Domain Model example runs without errors. */ +final class AppTest { + + @Test + void shouldExecuteApplicationWithoutException() { + assertDoesNotThrow(() -> App.main(new String[] {})); + } + +} diff --git a/domain-model/src/test/java/com/iluwatar/domainmodel/CustomerDaoImplTest.java b/domain-model/src/test/java/com/iluwatar/domainmodel/CustomerDaoImplTest.java new file mode 100644 index 000000000..cebd4f3c8 --- /dev/null +++ b/domain-model/src/test/java/com/iluwatar/domainmodel/CustomerDaoImplTest.java @@ -0,0 +1,164 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import javax.sql.DataSource; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.LocalDate; + +import static org.joda.money.CurrencyUnit.USD; +import static org.junit.jupiter.api.Assertions.*; + +class CustomerDaoImplTest { + + public static final String INSERT_CUSTOMER_SQL = "insert into CUSTOMERS values('customer', 100)"; + public static final String SELECT_CUSTOMERS_SQL = "select name, money from CUSTOMERS"; + public static final String INSERT_PURCHASES_SQL = + "insert into PURCHASES values('product', 'customer')"; + public static final String SELECT_PURCHASES_SQL = + "select product_name, customer_name from PURCHASES"; + + private DataSource dataSource; + private Product product; + private Customer customer; + private CustomerDao customerDao; + + @BeforeEach + void setUp() throws SQLException { + // create db schema + dataSource = TestUtils.createDataSource(); + + TestUtils.deleteSchema(dataSource); + TestUtils.createSchema(dataSource); + + // setup objects + customerDao = new CustomerDaoImpl(dataSource); + + customer = Customer.builder().name("customer").money(Money.of(CurrencyUnit.USD,100.0)).customerDao(customerDao).build(); + + product = + Product.builder() + .name("product") + .price(Money.of(USD, 100.0)) + .expirationDate(LocalDate.parse("2021-06-27")) + .productDao(new ProductDaoImpl(dataSource)) + .build(); + } + + @AfterEach + void tearDown() throws SQLException { + TestUtils.deleteSchema(dataSource); + } + + @Test + void shouldFindCustomerByName() throws SQLException { + var customer = customerDao.findByName("customer"); + + assertTrue(customer.isEmpty()); + + TestUtils.executeSQL(INSERT_CUSTOMER_SQL, dataSource); + + customer = customerDao.findByName("customer"); + + assertTrue(customer.isPresent()); + assertEquals("customer", customer.get().getName()); + assertEquals(Money.of(USD, 100), customer.get().getMoney()); + } + + @Test + void shouldSaveCustomer() throws SQLException { + customerDao.save(customer); + + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(SELECT_CUSTOMERS_SQL)) { + + assertTrue(rs.next()); + assertEquals(customer.getName(), rs.getString("name")); + assertEquals(customer.getMoney(), Money.of(USD, rs.getBigDecimal("money"))); + } + + assertThrows(SQLException.class, () -> customerDao.save(customer)); + } + + @Test + void shouldUpdateCustomer() throws SQLException { + TestUtils.executeSQL(INSERT_CUSTOMER_SQL, dataSource); + + customer.setMoney(Money.of(CurrencyUnit.USD, 99)); + + customerDao.update(customer); + + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(SELECT_CUSTOMERS_SQL)) { + + assertTrue(rs.next()); + assertEquals(customer.getName(), rs.getString("name")); + assertEquals(customer.getMoney(), Money.of(USD, rs.getBigDecimal("money"))); + assertFalse(rs.next()); + } + } + + @Test + void shouldAddProductToPurchases() throws SQLException { + TestUtils.executeSQL(INSERT_CUSTOMER_SQL, dataSource); + TestUtils.executeSQL(ProductDaoImplTest.INSERT_PRODUCT_SQL, dataSource); + + customerDao.addProduct(product, customer); + + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(SELECT_PURCHASES_SQL)) { + + assertTrue(rs.next()); + assertEquals(product.getName(), rs.getString("product_name")); + assertEquals(customer.getName(), rs.getString("customer_name")); + assertFalse(rs.next()); + } + } + + @Test + void shouldDeleteProductFromPurchases() throws SQLException { + TestUtils.executeSQL(INSERT_CUSTOMER_SQL, dataSource); + TestUtils.executeSQL(ProductDaoImplTest.INSERT_PRODUCT_SQL, dataSource); + TestUtils.executeSQL(INSERT_PURCHASES_SQL, dataSource); + + customerDao.deleteProduct(product, customer); + + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(SELECT_PURCHASES_SQL)) { + + assertFalse(rs.next()); + } + } +} diff --git a/domain-model/src/test/java/com/iluwatar/domainmodel/CustomerTest.java b/domain-model/src/test/java/com/iluwatar/domainmodel/CustomerTest.java new file mode 100644 index 000000000..3d27507ad --- /dev/null +++ b/domain-model/src/test/java/com/iluwatar/domainmodel/CustomerTest.java @@ -0,0 +1,112 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.sql.SQLException; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Optional; + +import static org.joda.money.CurrencyUnit.USD; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +class CustomerTest { + + private CustomerDao customerDao; + private Customer customer; + private Product product; + + @BeforeEach + void setUp() { + customerDao = mock(CustomerDao.class); + + customer = Customer.builder() + .name("customer") + .money(Money.of(CurrencyUnit.USD, 100.0)) + .customerDao(customerDao) + .build(); + + product = Product.builder() + .name("product") + .price(Money.of(USD, 100.0)) + .expirationDate(LocalDate.now().plusDays(10)) + .productDao(mock(ProductDao.class)) + .build(); + } + + @Test + void shouldSaveCustomer() throws SQLException { + when(customerDao.findByName("customer")).thenReturn(Optional.empty()); + + customer.save(); + + verify(customerDao, times(1)).save(customer); + + when(customerDao.findByName("customer")).thenReturn(Optional.of(customer)); + + customer.save(); + + verify(customerDao, times(1)).update(customer); + } + + @Test + void shouldAddProductToPurchases() { + product.setPrice(Money.of(USD, 200.0)); + + customer.buyProduct(product); + + assertEquals(customer.getPurchases(), new ArrayList<>()); + assertEquals(customer.getMoney(), Money.of(USD,100)); + + product.setPrice(Money.of(USD, 100.0)); + + customer.buyProduct(product); + + assertEquals(new ArrayList<>(Arrays.asList(product)), customer.getPurchases()); + assertEquals(Money.zero(USD), customer.getMoney()); + } + + @Test + void shouldRemoveProductFromPurchases() { + customer.setPurchases(new ArrayList<>(Arrays.asList(product))); + + customer.returnProduct(product); + + assertEquals(new ArrayList<>(), customer.getPurchases()); + assertEquals(Money.of(USD, 200), customer.getMoney()); + + customer.returnProduct(product); + + assertEquals(new ArrayList<>(), customer.getPurchases()); + assertEquals(Money.of(USD, 200), customer.getMoney()); + } +} + diff --git a/domain-model/src/test/java/com/iluwatar/domainmodel/ProductDaoImplTest.java b/domain-model/src/test/java/com/iluwatar/domainmodel/ProductDaoImplTest.java new file mode 100644 index 000000000..1a7000672 --- /dev/null +++ b/domain-model/src/test/java/com/iluwatar/domainmodel/ProductDaoImplTest.java @@ -0,0 +1,127 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import org.joda.money.Money; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import javax.sql.DataSource; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.LocalDate; + +import static org.joda.money.CurrencyUnit.USD; +import static org.junit.jupiter.api.Assertions.*; + +class ProductDaoImplTest { + + public static final String INSERT_PRODUCT_SQL = + "insert into PRODUCTS values('product', 100, DATE '2021-06-27')"; + public static final String SELECT_PRODUCTS_SQL = + "select name, price, expiration_date from PRODUCTS"; + + private DataSource dataSource; + private ProductDao productDao; + private Product product; + + @BeforeEach + void setUp() throws SQLException { + // create schema + dataSource = TestUtils.createDataSource(); + + TestUtils.deleteSchema(dataSource); + TestUtils.createSchema(dataSource); + + // setup objects + productDao = new ProductDaoImpl(dataSource); + + product = + Product.builder() + .name("product") + .price(Money.of(USD, 100.0)) + .expirationDate(LocalDate.parse("2021-06-27")) + .productDao(productDao) + .build(); + } + + @AfterEach + void tearDown() throws SQLException { + TestUtils.deleteSchema(dataSource); + } + + @Test + void shouldFindProductByName() throws SQLException { + var product = productDao.findByName("product"); + + assertTrue(product.isEmpty()); + + TestUtils.executeSQL(INSERT_PRODUCT_SQL, dataSource); + + product = productDao.findByName("product"); + + assertTrue(product.isPresent()); + assertEquals("product", product.get().getName()); + assertEquals(Money.of(USD, 100), product.get().getPrice()); + assertEquals(LocalDate.parse("2021-06-27"), product.get().getExpirationDate()); + } + + @Test + void shouldSaveProduct() throws SQLException { + + productDao.save(product); + + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(SELECT_PRODUCTS_SQL)) { + + assertTrue(rs.next()); + assertEquals(product.getName(), rs.getString("name")); + assertEquals(product.getPrice(), Money.of(USD, rs.getBigDecimal("price"))); + assertEquals(product.getExpirationDate(), rs.getDate("expiration_date").toLocalDate()); + } + + assertThrows(SQLException.class, () -> productDao.save(product)); + } + + @Test + void shouldUpdateProduct() throws SQLException { + TestUtils.executeSQL(INSERT_PRODUCT_SQL, dataSource); + + product.setPrice(Money.of(USD, 99.0)); + + productDao.update(product); + + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(SELECT_PRODUCTS_SQL)) { + + assertTrue(rs.next()); + assertEquals(product.getName(), rs.getString("name")); + assertEquals(product.getPrice(), Money.of(USD, rs.getBigDecimal("price"))); + assertEquals(product.getExpirationDate(), rs.getDate("expiration_date").toLocalDate()); + } + } +} diff --git a/domain-model/src/test/java/com/iluwatar/domainmodel/ProductTest.java b/domain-model/src/test/java/com/iluwatar/domainmodel/ProductTest.java new file mode 100644 index 000000000..2da1a8023 --- /dev/null +++ b/domain-model/src/test/java/com/iluwatar/domainmodel/ProductTest.java @@ -0,0 +1,78 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import org.joda.money.Money; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.sql.SQLException; +import java.time.LocalDate; +import java.util.Optional; + +import static org.joda.money.CurrencyUnit.USD; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +class ProductTest { + + private ProductDao productDao; + private Product product; + + @BeforeEach + void setUp() { + productDao = mock(ProductDaoImpl.class); + + product = Product.builder() + .name("product") + .price(Money.of(USD, 100.0)) + .expirationDate(LocalDate.now().plusDays(10)) + .productDao(productDao) + .build(); + } + + @Test + void shouldSaveProduct() throws SQLException { + when(productDao.findByName("product")).thenReturn(Optional.empty()); + + product.save(); + + verify(productDao, times(1)).save(product); + + when(productDao.findByName("product")).thenReturn(Optional.of(product)); + + product.save(); + + verify(productDao, times(1)).update(product); + } + + @Test + void shouldGetSalePriceOfProduct() { + assertEquals(Money.of(USD, 100), product.getSalePrice()); + + product.setExpirationDate(LocalDate.now().plusDays(2)); + + assertEquals(Money.of(USD, 80), product.getSalePrice()); + } +} diff --git a/domain-model/src/test/java/com/iluwatar/domainmodel/TestUtils.java b/domain-model/src/test/java/com/iluwatar/domainmodel/TestUtils.java new file mode 100644 index 000000000..e04eccb4c --- /dev/null +++ b/domain-model/src/test/java/com/iluwatar/domainmodel/TestUtils.java @@ -0,0 +1,53 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.domainmodel; + +import org.h2.jdbcx.JdbcDataSource; + +import javax.sql.DataSource; +import java.sql.SQLException; + +public class TestUtils { + + public static void executeSQL( String sql, DataSource dataSource) throws SQLException { + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement()) { + statement.executeUpdate(sql); + } + } + + public static void createSchema(DataSource dataSource) throws SQLException { + TestUtils.executeSQL(App.CREATE_SCHEMA_SQL, dataSource); + } + + public static void deleteSchema(DataSource dataSource) throws SQLException { + TestUtils.executeSQL(App.DELETE_SCHEMA_SQL, dataSource); + } + + public static DataSource createDataSource() { + var dataSource = new JdbcDataSource(); + dataSource.setURL(App.H2_DB_URL); + return dataSource; + } +} diff --git a/pom.xml b/pom.xml index 31cf03b4d..1ebe0ad23 100644 --- a/pom.xml +++ b/pom.xml @@ -232,6 +232,7 @@ table-module presentation lockable-object + domain-model @@ -379,12 +380,12 @@ ${system-lambda.version} test - - commons-io - commons-io - ${commons-io.version} - - + + commons-io + commons-io + ${commons-io.version} + + diff --git a/strategy/pom.xml b/strategy/pom.xml index b3d1589c3..e96dc41d3 100644 --- a/strategy/pom.xml +++ b/strategy/pom.xml @@ -59,7 +59,7 @@ - com.iluwatar.subclasssandbox.App + com.iluwatar.strategy.App diff --git a/table-module/README.md b/table-module/README.md index 318a2694d..1cbc3a982 100644 --- a/table-module/README.md +++ b/table-module/README.md @@ -125,7 +125,7 @@ Use the Table Module Pattern when - [Transaction Script](https://java-design-patterns.com/patterns/transaction-script/) -- Domain Model +- [Domain Model](https://java-design-patterns.com/patterns/domain-model/) ## Credits From 3f654ab0c897e222492fc3518eb80a3cc906752f Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 22 Jul 2021 17:00:52 +0300 Subject: [PATCH 09/11] docs: add AndriyPyzh as a contributor for code (#1804) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 6fa850e92..d6de42921 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1559,6 +1559,15 @@ "contributions": [ "translation" ] + }, + { + "login": "AndriyPyzh", + "name": "AndriyPyzh", + "avatar_url": "https://avatars.githubusercontent.com/u/57706635?v=4", + "profile": "https://github.com/AndriyPyzh", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 4, diff --git a/README.md b/README.md index 5dd071fa1..0013458e9 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns) [![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![All Contributors](https://img.shields.io/badge/all_contributors-171-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-172-orange.svg?style=flat-square)](#contributors-)
    @@ -331,6 +331,7 @@ This project is licensed under the terms of the MIT license.

    Xenilo137

    💻
    Samuel Souza

    💻
    Marlo Henrique

    🌍 +
    AndriyPyzh

    💻 From d36efdbc7c2bc7cbaf4b2bdd8a34b9bc12403330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sun, 25 Jul 2021 14:58:54 +0300 Subject: [PATCH 10/11] TASK: Add language to yaml front matter (#1806) --- domain-model/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/domain-model/README.md b/domain-model/README.md index 89cefee80..696fc41fd 100644 --- a/domain-model/README.md +++ b/domain-model/README.md @@ -4,11 +4,15 @@ title: Domain Model folder: domain-model permalink: /patterns/domain-model/ categories: Architectural +language: en tags: - Domain --- + ## Intent + Domain model pattern provides an object-oriented way of dealing with complicated logic. Instead of having one procedure that handles all business logic for a user action there are multiple objects and each of them handles a slice of domain logic that is relevant to it. + ## Explanation Real world example From c5a4068e84f2dfd4dd6cd76125fcc66fb87679d2 Mon Sep 17 00:00:00 2001 From: Mike Liu Date: Sun, 1 Aug 2021 22:55:54 +0800 Subject: [PATCH 11/11] docs: Translation for zh (#1805) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add state and callback pattern * add command and template-method pattern * add iterator pattern * add bridege and DI pattern * fix issue #1600 * add converter,proxy,visitor pattern * add caching,composite,delegation,dirty-flag,interpreter patterns * add dao and producer-consumer * add dto and provate class data pattern * fix #1646 png path problems * fix #1646 composite png path case problem * add abstract document pattern and version-number pattern * add ambassador pattern * add acyclic-visitor and api-gateway pattern * add abstract-factory pattern * add active-object pattern * add aggregator-microservices and arrange-act-assert pattern * update async-method-invocation pattern * add balking and business-delegate pattern * add bytecode and circuit-break pattern * update arrange/act/assert pattern problems * add csch pattern * add language code, correct pic path * #1805 update permalink Co-authored-by: Subhrodip Mohanta Co-authored-by: Mike Co-authored-by: Ilkka Seppälä --- localization/zh/abstract-document/README.md | 4 +- localization/zh/abstract-factory/README.md | 4 +- localization/zh/active-object/README.md | 4 +- localization/zh/acyclic-visitor/README.md | 4 +- localization/zh/adapter/README.md | 4 +- .../zh/aggregator-microservices/README.md | 4 +- localization/zh/ambassador/README.md | 4 +- localization/zh/api-gateway/README.md | 4 +- localization/zh/arrange-act-assert/README.md | 10 +- .../zh/async-method-invocation/README.md | 57 +++-- localization/zh/balking/README.md | 48 ++-- localization/zh/bridge/README.md | 4 +- localization/zh/builder/README.md | 4 +- localization/zh/business-delegate/README.md | 50 ++-- localization/zh/bytecode/README.md | 235 ++++++++++++++++++ localization/zh/caching/README.md | 4 +- localization/zh/callback/README.md | 4 +- localization/zh/chain/README.md | 4 +- localization/zh/circuit-breaker/README.md | 115 +++++---- .../zh/cloud-static-content-hosting/README.md | 134 ++++++++++ localization/zh/collection-pipeline/README.md | 3 +- localization/zh/command/README.md | 4 +- localization/zh/composite-entity/README.md | 3 +- localization/zh/composite/README.md | 4 +- localization/zh/converter/README.md | 4 +- localization/zh/dao/README.md | 4 +- localization/zh/data-bus/README.md | 4 +- localization/zh/data-mapper/README.md | 3 +- .../zh/data-transfer-object/README.md | 4 +- localization/zh/decorator/README.md | 4 +- localization/zh/delegation/README.md | 4 +- .../zh/dependency-injection/README.md | 4 +- localization/zh/dirty-flag/README.md | 4 +- .../zh/double-checked-locking/README.md | 3 +- localization/zh/facade/README.md | 4 +- localization/zh/factory-kit/README.md | 3 +- localization/zh/factory-method/README.md | 4 +- localization/zh/factory/README.md | 3 +- localization/zh/interpreter/README.md | 4 +- localization/zh/iterator/README.md | 4 +- localization/zh/observer/README.md | 4 +- localization/zh/private-class-data/README.md | 4 +- localization/zh/producer-consumer/README.md | 4 +- localization/zh/proxy/README.md | 4 +- localization/zh/sharding/README.md | 3 +- localization/zh/state/README.md | 4 +- localization/zh/strategy/README.md | 4 +- localization/zh/template-method/README.md | 4 +- localization/zh/version-number/README.md | 6 +- localization/zh/visitor/README.md | 4 +- 50 files changed, 595 insertions(+), 221 deletions(-) create mode 100644 localization/zh/bytecode/README.md create mode 100644 localization/zh/cloud-static-content-hosting/README.md diff --git a/localization/zh/abstract-document/README.md b/localization/zh/abstract-document/README.md index 4bcff1da7..5bcb5e1e2 100644 --- a/localization/zh/abstract-document/README.md +++ b/localization/zh/abstract-document/README.md @@ -2,7 +2,7 @@ layout: pattern title: Abstract Document folder: abstract-document -permalink: /patterns/abstract-document/zh +permalink: /patterns/abstract-document/ categories: Structural language: zh tags: @@ -166,7 +166,7 @@ public class Car extends AbstractDocument implements HasModel, HasPrice, HasPart ## 类图 -![alt text](../../abstract-document/etc/abstract-document.png "Abstract Document Traits and Domain") +![alt text](../../../abstract-document/etc/abstract-document.png "Abstract Document Traits and Domain") ## 适用性 diff --git a/localization/zh/abstract-factory/README.md b/localization/zh/abstract-factory/README.md index b16be817a..0b2b109e4 100644 --- a/localization/zh/abstract-factory/README.md +++ b/localization/zh/abstract-factory/README.md @@ -2,7 +2,7 @@ layout: pattern title: Abstract Factory folder: abstract-factory -permalink: /patterns/abstract-factory/zh +permalink: /patterns/abstract-factory/ categories: Creational language: zh tags: @@ -168,7 +168,7 @@ public static void main(String[] args) { ## 类图 -![alt text](../../abstract-factory/etc/abstract-factory.urm.png "Abstract Factory class diagram") +![alt text](../../../abstract-factory/etc/abstract-factory.urm.png "Abstract Factory class diagram") ## 适用性 diff --git a/localization/zh/active-object/README.md b/localization/zh/active-object/README.md index c8e23c9c1..ae1a1724f 100644 --- a/localization/zh/active-object/README.md +++ b/localization/zh/active-object/README.md @@ -2,7 +2,7 @@ layout: pattern title: Active Object folder: active-object -permalink: /patterns/active-object/zh +permalink: /patterns/active-object/ categories: Concurrency language: zh tags: @@ -122,4 +122,4 @@ public class Orc extends ActiveCreature { ## 类图 -![alt text](../../active-object/etc/active-object.urm.PNG "Active Object class diagram") +![alt text](../../../active-object/etc/active-object.urm.PNG "Active Object class diagram") diff --git a/localization/zh/acyclic-visitor/README.md b/localization/zh/acyclic-visitor/README.md index 31c062457..965dc7a67 100644 --- a/localization/zh/acyclic-visitor/README.md +++ b/localization/zh/acyclic-visitor/README.md @@ -2,7 +2,7 @@ layout: pattern title: Acyclic Visitor folder: acyclic-visitor -permalink: /patterns/acyclic-visitor/zh +permalink: /patterns/acyclic-visitor/ categories: Behavioral language: zh tags: @@ -123,7 +123,7 @@ public class ConfigureForUnixVisitor implements ZoomVisitor { ## 类图 -![alt text](../../acyclic-visitor/etc/acyclic-visitor.png "Acyclic Visitor") +![alt text](../../../acyclic-visitor/etc/acyclic-visitor.png "Acyclic Visitor") ## 适用性 diff --git a/localization/zh/adapter/README.md b/localization/zh/adapter/README.md index 2e440d7bf..6add248fe 100644 --- a/localization/zh/adapter/README.md +++ b/localization/zh/adapter/README.md @@ -2,7 +2,7 @@ layout: pattern title: Adapter folder: adapter -permalink: /patterns/adapter/zh +permalink: /patterns/adapter/ categories: Structural language: zh tags: @@ -94,7 +94,7 @@ captain.row(); ``` ## 类图 -![alt text](../../adapter/etc/adapter.urm.png "Adapter class diagram") +![alt text](../../../adapter/etc/adapter.urm.png "Adapter class diagram") ## 应用 diff --git a/localization/zh/aggregator-microservices/README.md b/localization/zh/aggregator-microservices/README.md index 10b5ffeaa..dbca273c1 100644 --- a/localization/zh/aggregator-microservices/README.md +++ b/localization/zh/aggregator-microservices/README.md @@ -2,7 +2,7 @@ layout: pattern title: Aggregator Microservices folder: aggregator-microservices -permalink: /patterns/aggregator-microservices/zh +permalink: /patterns/aggregator-microservices/ categories: Architectural language: zh tags: @@ -95,7 +95,7 @@ curl http://localhost:50004/product ## 类图 -![alt text](../../aggregator-microservices/aggregator-service/etc/aggregator-service.png "Aggregator Microservice") +![alt text](../../../aggregator-microservices/aggregator-service/etc/aggregator-service.png "Aggregator Microservice") ## 适用性 diff --git a/localization/zh/ambassador/README.md b/localization/zh/ambassador/README.md index f96d87371..7b07e7b05 100644 --- a/localization/zh/ambassador/README.md +++ b/localization/zh/ambassador/README.md @@ -2,7 +2,7 @@ layout: pattern title: Ambassador folder: ambassador -permalink: /patterns/ambassador/zh +permalink: /patterns/ambassador/ categories: Structural language: zh tags: @@ -167,7 +167,7 @@ Service result: -1 ## 类图 -![alt text](../../ambassador/etc/ambassador.urm.png "Ambassador class diagram") +![alt text](../../../ambassador/etc/ambassador.urm.png "Ambassador class diagram") ## 适用性 diff --git a/localization/zh/api-gateway/README.md b/localization/zh/api-gateway/README.md index a41f004ca..2ce28b0d2 100644 --- a/localization/zh/api-gateway/README.md +++ b/localization/zh/api-gateway/README.md @@ -2,7 +2,7 @@ layout: pattern title: API Gateway folder: api-gateway -permalink: /patterns/api-gateway/zh +permalink: /patterns/api-gateway/ categories: Architectural language: zh tags: @@ -123,7 +123,7 @@ public class ApiGateway { ``` ## 类图 -![alt text](../../api-gateway/etc/api-gateway.png "API Gateway") +![alt text](../../../api-gateway/etc/api-gateway.png "API Gateway") ## 适用性 diff --git a/localization/zh/arrange-act-assert/README.md b/localization/zh/arrange-act-assert/README.md index 67849b8ac..b4b411206 100644 --- a/localization/zh/arrange-act-assert/README.md +++ b/localization/zh/arrange-act-assert/README.md @@ -2,7 +2,7 @@ layout: pattern title: Arrange/Act/Assert folder: arrange-act-assert -permalink: /patterns/arrange-act-assert/zh +permalink: /patterns/arrange-act-assert/ categories: Idiom language: zh tags: @@ -73,10 +73,7 @@ public class Cash { } ``` -Then we write our unit tests according to Arrange/Act/Assert pattern. Notice the clearly -separated steps for each unit test. - -然后我们根据Arrange / Act / Assert模式编写单元测试。 注意每个单元测试的步骤是分开的清晰的。 +然后我们根据安排/ 执行 / 断言模式编写单元测试。 注意每个单元测试的步骤是分开的清晰的。 ```java class CashAAATest { @@ -129,9 +126,8 @@ class CashAAATest { ## 适用性 -使用 Arrange/Act/Assert 模式当 +使用 安排/执行/断言 模式当 -* You need to structure your unit tests so that they're easier to read, maintain, and enhance. * 你需要结构化你的单元测试代码这样它们可以更好的阅读,维护和增强。 ## 鸣谢 diff --git a/localization/zh/async-method-invocation/README.md b/localization/zh/async-method-invocation/README.md index b71cd18f3..f5739c1e9 100644 --- a/localization/zh/async-method-invocation/README.md +++ b/localization/zh/async-method-invocation/README.md @@ -4,33 +4,32 @@ title: Async Method Invocation folder: async-method-invocation permalink: /patterns/async-method-invocation/ categories: Concurrency +language: zh tags: - Reactive --- -## 含义 +## 意图 -异步方法是一种调用线程在等待任务结果时候不会被阻塞的模式。该模式提供了对多个任务的并行处理,并通过回调或等待,在所有任务完成后在提供结果读取。 +异步方法调用是一个调用线程在等待任务结果时不会阻塞的模式。模式为多个独立的任务提供并行的处理方式并且通过回调或等到它们全部完成来接收任务结果。 ## 解释 -真实世界案例 +真实世界例子 -> 发射太空火箭是一项令人兴奋的事业。在任务指挥部下达发射命令后, 经过一些未确定的时间,火箭要么成功发射,要么重演挑战者悲剧。 +> 发射火箭是一项令人激动的事务。任务指挥官发出了发射命令,经过一段不确定的时间后,火箭要么成功发射,要么惨遭失败。 -简而言之 +通俗地说 -> 异步方法调用开始任务处理并,在任务结果准备好之前立即返回。任务处理的结果会在稍后再返回给调用者。 +> 异步方法调用开始任务处理,并在任务完成之前立即返回。 任务处理的结果稍后返回给调用方。 -维基百科的解释 +维基百科说 -> 在多线程计算机编程中,异步方法调用(AMI),也被称为异步方法调用或异步模式。这是一种设计模式,在这种模式下,调用点在等待被调用代码完成时不会被阻塞。相反,当返回点到达时,调用线程会得到通知。轮询结果是一种不受欢迎的选择。 +> 在多线程计算机编程中,异步方法调用(AMI),也称为异步方法调用或异步模式,是一种设计模式,其中在等待被调用的代码完成时不会阻塞调用站点。 而是在执行结果到达时通知调用线程。轮询调用结果是不希望的选项。 -**编程示例** +**程序示例** -在这个例子中,我们正在发射太空火箭和部署月球车。 - -该应用演示了异步方法调用模式。该模式的关键部分是 `AsyncResult`,它是一个异步计算值的中间容器,`AsyncCallback` 可以在任务完成时提供执行行动作,`AsyncExecutor` 负责管理异步任务的执行。 +在此示例中,我们正在发射太空火箭并部署月球漫游车。该应用演示了异步方法调用模式。 模式的关键部分是`AsyncResult`(用于异步评估值的中间容器),`AsyncCallback`(可以在任务完成时被执行)和`AsyncExecutor`(用于管理异步任务的执行)。 ```java public interface AsyncResult { @@ -54,7 +53,7 @@ public interface AsyncExecutor { } ``` -`ThreadAsyncExecutor` 是 `AsyncExecutor` 的一个实现。接下来将着重说明它的一些关键部分。 +`ThreadAsyncExecutor`是`AsyncExecutor`的实现。 接下来将突出显示其一些关键部分。 ```java public class ThreadAsyncExecutor implements AsyncExecutor { @@ -91,14 +90,14 @@ public class ThreadAsyncExecutor implements AsyncExecutor { } ``` -然后我们准备发射一些火箭,看看所有东西是如何一起运作的。 +然后,我们准备发射一些火箭,看看一切是如何协同工作的。 ```java public static void main(String[] args) throws Exception { - // construct a new executor that will run async tasks + // 构造一个将执行异步任务的新执行程序 var executor = new ThreadAsyncExecutor(); - // start few async tasks with varying processing times, two last with callback handlers + // 以不同的处理时间开始一些异步任务,最后两个使用回调处理程序 final var asyncResult1 = executor.startProcess(lazyval(10, 500)); final var asyncResult2 = executor.startProcess(lazyval("test", 300)); final var asyncResult3 = executor.startProcess(lazyval(50L, 700)); @@ -106,11 +105,11 @@ public static void main(String[] args) throws Exception { final var asyncResult5 = executor.startProcess(lazyval("callback", 600), callback("Deploying lunar rover")); - // emulate processing in the current thread while async tasks are running in their own threads - Thread.sleep(350); // Oh boy, we are working hard here + // 在当前线程中模拟异步任务正在它们自己的线程中执行 + Thread.sleep(350); // 哦,兄弟,我们在这很辛苦 log("Mission command is sipping coffee"); - // wait for completion of the tasks + // 等待任务完成 final var result1 = executor.endProcess(asyncResult1); final var result2 = executor.endProcess(asyncResult2); final var result3 = executor.endProcess(asyncResult3); @@ -118,13 +117,14 @@ public static void main(String[] args) throws Exception { asyncResult5.await(); // log the results of the tasks, callbacks log immediately when complete + // 记录任务结果的日志, 回调的日志会在回调完成时立刻记录 log("Space rocket <" + result1 + "> launch complete"); log("Space rocket <" + result2 + "> launch complete"); log("Space rocket <" + result3 + "> launch complete"); } ``` -以下是控制台输出。 +这是程序控制台的输出。 ```java 21:47:08.227 [executor-2] INFO com.iluwatar.async.method.invocation.App - Space rocket launched successfully @@ -140,22 +140,21 @@ public static void main(String[] args) throws Exception { 21:47:08.618 [main] INFO com.iluwatar.async.method.invocation.App - Space rocket <50> launch complete ``` -## 类图 +# 类图 -![alt text](../../async-method-invocation/etc/async-method-invocation.png "Async Method Invocation") +![alt text](../../../async-method-invocation/etc/async-method-invocation.png "Async Method Invocation") -## 适用场景 +## 适用性 -在以下场景可以使用异步调用模式 +在以下情况下使用异步方法调用模式 -* 你有多有可以并行执行的独立任务 -* 你需要提高一组串行任务的性能 -* 你的处理能力有限、或者有长期运行的任务,调用者不应该等待任务所有任务运行结束 +* 您有多个可以并行运行的独立任务 +* 您需要提高一组顺序任务的性能 +* 您的处理能力或长时间运行的任务数量有限,并且调用方不应等待任务执行完毕 -## 现实示例 +## 真实世界例子 * [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html) * [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html) * [ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html) * [Task-based Asynchronous Pattern](https://msdn.microsoft.com/en-us/library/hh873175.aspx) - diff --git a/localization/zh/balking/README.md b/localization/zh/balking/README.md index 9d8ac095d..ef1b12e3f 100644 --- a/localization/zh/balking/README.md +++ b/localization/zh/balking/README.md @@ -4,33 +4,34 @@ title: Balking folder: balking permalink: /patterns/balking/ categories: Concurrency +language: zh tags: - Decoupling --- -## 含义 +## 意图 -阻止模式用于防止一个对象在不完整或不适当的状态下执行某段代码。 +止步模式用于防止对象在不完整或不合适的状态下执行某些代码。 ## 解释 -真实世界的案例 +真实世界例子 -> 洗衣机里有一个用于启动衣物洗涤的启动按钮。当洗衣机没有启动时,该按钮可以正常按下生效,但如果洗衣机已经在洗衣服了,再按下按钮就不生效了。 +> 洗衣机中有一个开始按钮,用于启动衣物洗涤。当洗衣机处于非活动状态时,按钮将按预期工作,但是如果已经在洗涤,则按钮将不起任何作用。 -简而言之 +通俗地说 -> 使用阻止模式,只有当对象处于特定状态时,才会执行某段代码。 +> 使用止步模式,仅当对象处于特定状态时才执行特定代码。 -维基百科的解释 +维基百科说 -> 阻止模式是一种软件设计模式,它只在对象处于特定状态时对其执行动作。例如,如果一个对象读取 ZIP 文件,当 ZIP 文件没有打开时,如果一个方法在该对象上调用一个获取方法,该对象就会对阻止这个请求。 +> 禁止模式是一种软件设计模式,仅当对象处于特定状态时才对对象执行操作。例如,一个对象读取zip压缩文件并在压缩文件没打开的时候调用get方法,对象将在请求的时候”止步“。 -**编程示例** +**程序示例** -在这个例子的实现中,`WashingMachine` 对象存在 2 种状态: `ENABLED` 和 `WASHING`。如果该对象处于 `ENABLED` 状态,则使用一个线程安全的方法可以其状态改变为 `WASHING`。在另一方面,如果它已经处于 `WASHING` 状态,而任何其他线程执行了 `wash()`,它不会执行该指令,而是什么都不做就返回。 +在此示例中,` WashingMachine`是一个具有两个状态的对象,可以处于两种状态:ENABLED和WASHING。 如果机器已启用,则使用线程安全方法将状态更改为WASHING。 另一方面,如果已经进行了清洗并且任何其他线程执行`wash()`,则它将不执行该操作,而是不执行任何操作而返回。 -以下是 `WashingMachine` 类的相关代码。 +这里是`WashingMachine` 类相关的部分。 ```java @Slf4j @@ -69,7 +70,7 @@ public class WashingMachine { } ``` -以下是 `WashingMachine` 使用的简单 `DelayProvider` 接口。 +这里是一个`WashingMachine`所使用的`DelayProvider`简单接口。 ```java public interface DelayProvider { @@ -77,7 +78,7 @@ public interface DelayProvider { } ``` -现在我们介绍一下使用 `WashingMachine` 的应用。 +现在,我们使用`WashingMachine`介绍该应用程序。 ```java public static void main(String... args) { @@ -96,7 +97,7 @@ public interface DelayProvider { } ``` -以下是程序的控制台输出。 +下面是程序的输出。 ``` 14:02:52.268 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Actual machine state: ENABLED @@ -110,20 +111,21 @@ public interface DelayProvider { ## 类图 -![alt text](../../balking/etc/balking.png "Balking") +![alt text](../../../balking/etc/balking.png "Balking") -## 适用场景 +## 适用性 -在以下情况下可以使用阻止模式: -* 你想要在某个对象上调用一个动作,只有当该对象处于特定状态时才允许该调用。 -* 对象一般只处于容易暂时阻止的状态,只不过该时间是未知的。 +使用止步模式当 -## 教学 +* 您只想在对象处于特定状态时才对其调用操作 +* 对象通常仅处于容易暂时停止但状态未知的状态 -* [Guarded Suspension Pattern](https://java-design-patterns.com/patterns/guarded-suspension/) -* [Double Checked Locking Pattern](https://java-design-patterns.com/patterns/double-checked-locking/) +## 相关模式 -## 引用 +* [保护性暂挂模式](https://java-design-patterns.com/patterns/guarded-suspension/) +* [双重检查锁模式](https://java-design-patterns.com/patterns/double-checked-locking/) + +## 鸣谢 * [Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML, 2nd Edition, Volume 1](https://www.amazon.com/gp/product/0471227293/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0471227293&linkId=0e39a59ffaab93fb476036fecb637b99) diff --git a/localization/zh/bridge/README.md b/localization/zh/bridge/README.md index d4773583f..b1b770781 100644 --- a/localization/zh/bridge/README.md +++ b/localization/zh/bridge/README.md @@ -2,7 +2,7 @@ layout: pattern title: Bridge folder: bridge -permalink: /patterns/bridge/zh +permalink: /patterns/bridge/ categories: Structural language: zh tags: @@ -184,7 +184,7 @@ hammer.unwield(); ## 类图 -![alt text](../../bridge/etc/bridge.urm.png "Bridge class diagram") +![alt text](../../../bridge/etc/bridge.urm.png "Bridge class diagram") ## 适用性 diff --git a/localization/zh/builder/README.md b/localization/zh/builder/README.md index 6987dc6a4..953a2a5ad 100644 --- a/localization/zh/builder/README.md +++ b/localization/zh/builder/README.md @@ -2,7 +2,7 @@ layout: pattern title: Builder folder: builder -permalink: /patterns/builder/zh +permalink: /patterns/builder/ categories: Creational language: zh tags: @@ -114,7 +114,7 @@ var mage = new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor. ## 类图 -![alt text](../../builder/etc/builder.urm.png "Builder class diagram") +![alt text](../../../builder/etc/builder.urm.png "Builder class diagram") ## 适用性 diff --git a/localization/zh/business-delegate/README.md b/localization/zh/business-delegate/README.md index 225d81556..bef906987 100644 --- a/localization/zh/business-delegate/README.md +++ b/localization/zh/business-delegate/README.md @@ -4,36 +4,32 @@ title: Business Delegate folder: business-delegate permalink: /patterns/business-delegate/ categories: Structural +language: zh tags: - Decoupling --- -## 含义 +## 意图 -业务委托模式(译者:国内也有翻译成业务代表模式)在表现层和业务层之间增加了一个抽象层。通过使用该模式,我们获得了各层之间的松散耦合,并封装了关于如何定位、连接和与构成应用程序的业务对象进行交互的知识。 +业务委托模式在表示层和业务层之间添加了一个抽象层。 通过使用该模式,我们获得了各层之间的松散耦合,并封装了有关如何定位,连接到组成应用程序的业务对象以及与之交互的逻辑。 ## 解释 -真实世界的案例 +真实世界例子 -> 一个手机应用程序承诺将现有的任何电影传输到你的手机上。它捕获了用户的搜索关键字内容,并将其传递给业务委托层。业务委托层选择最合适的视频流服务,并从该服务进行视频播放。 +> 手机应用程序承诺将现有的任何电影流式传输到您的手机。它捕获用户的搜索字符串,并将其传递给业务委托层。业务委托层选择最合适的视频流服务,然后从那里播放视频。 -简而言之 +通俗的说 -> 业务委托模式在表现层和业务层之间增加了一个抽象层。 +> 业务委托模式在表示层和业务层之间添加了一个抽象层。 -维基百科的解释 +维基百科说 -> Business delegate is a Java EE design pattern. This pattern is directing to reduce the coupling -> in between business services and the connected presentation tier, and to hide the implementation -> details of services (including lookup and accessibility of EJB architecture). Business delegates -> acts as an adaptor to invoke business objects from the presentation tier. -> -> 业务委托模式是一种 Java EE 设计模式。这种模式旨在减少业务服务和所连接的表现层之间的耦合度,并隐藏服务的实现细节(包括 EJB 架构的查询和可访问性)。业务代表作为一个适配器,从表现层调用业务对象。 +> 业务委托是一种Java EE设计模式。 该模式旨在减少业务服务与连接的表示层之间的耦合,并隐藏服务的实现细节(包括EJB体系结构的查找和可访问性)。 业务代表充当适配器,以从表示层调用业务对象。 -**编程示例** +**程序示例** -首先,我们实现了一个视频流服务的抽象,和几个具体实现。 +首先,我们有视频流服务的抽象类和一些它的实现。 ```java public interface VideoStreamingService { @@ -57,7 +53,7 @@ public class YouTubeService implements VideoStreamingService { } ``` -接下来,我们实现一个查询服务,用于决定使用哪个视频流服务。 +然后我们有一个查找服务来决定我们使用哪个视频流服务。 ```java @Setter @@ -76,7 +72,7 @@ public class BusinessLookup { } ``` -业务委托层使用业务查询,将电影播放请求路由到合适的视频流服务。 +业务委托类使用业务查找服务将电影播放请求路由到合适的视频流服务。 ```java @Setter @@ -108,7 +104,7 @@ public class MobileClient { } ``` -最后,我们展示一下这个示例完整的操作。 +最后我们展示完整示例。 ```java public static void main(String[] args) { @@ -127,7 +123,7 @@ public class MobileClient { } ``` -以下是终端输出的内容。 +这是控制台的输出。 ``` 21:15:33.790 [main] INFO com.iluwatar.business.delegate.NetflixService - NetflixService is now processing @@ -136,25 +132,25 @@ public class MobileClient { ## 类图 -![alt text](../../business-delegate/etc/business-delegate.urm.png "Business Delegate") +![alt text](../../../business-delegate/etc/business-delegate.urm.png "Business Delegate") ## 相关模式 -* [Service locator pattern](https://java-design-patterns.com/patterns/service-locator/) +* [服务定位器模式](https://java-design-patterns.com/patterns/service-locator/) -## 适用场景 +## 适用性 -业务委托模式的适用场景: +使用业务委托模式当 -* 你希望表现层和业务层之间是松耦合的。 -* 你想要协调对多个业务服务的调用。 -* 你想要对服务查询、服务调用进行封装。 +* 你希望表示层和业务层之间的松散耦合 +* 你想编排对多个业务服务的调用 +* 你希望封装查找服务和服务调用 ## 教程 * [Business Delegate Pattern at TutorialsPoint](https://www.tutorialspoint.com/design_pattern/business_delegate_pattern.htm) -## 引用 +## 鸣谢 * [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) * [Core J2EE Patterns: Best Practices and Design Strategies](https://www.amazon.com/gp/product/0130648841/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0130648841&linkId=a0100de2b28c71ede8db1757fb2b5947) diff --git a/localization/zh/bytecode/README.md b/localization/zh/bytecode/README.md new file mode 100644 index 000000000..4a280deaa --- /dev/null +++ b/localization/zh/bytecode/README.md @@ -0,0 +1,235 @@ +--- +layout: pattern +title: Bytecode +folder: bytecode +permalink: /patterns/bytecode/ +categories: Behavioral +language: zh +tags: + - Game programming +--- + +## 意图 + +允许编码行为作为虚拟机的指令。 + +## 解释 + +真实世界例子 + +> 一个团队正在开发一款新的巫师对战游戏。巫师的行为需要经过精心的调整和上百次的游玩测试。每次当游戏设计师想改变巫师行为时都让程序员去修改代码这是不妥的,所以巫师行为以数据驱动的虚拟机方式实现。 + +通俗地说 + +> 字节码模式支持由数据而不是代码驱动的行为。 + +[Gameprogrammingpatterns.com](https://gameprogrammingpatterns.com/bytecode.html) 中做了如下阐述: + +> 指令集定义了可以执行的低级操作。一系列指令被编码为字节序列。虚拟机一次一条地执行这些指令,中间的值用栈处理。通过组合指令,可以定义复杂的高级行为。 + +**程序示例** + +其中最重要的游戏对象是`巫师`类。 + +```java +@AllArgsConstructor +@Setter +@Getter +@Slf4j +public class Wizard { + + private int health; + private int agility; + private int wisdom; + private int numberOfPlayedSounds; + private int numberOfSpawnedParticles; + + public void playSound() { + LOGGER.info("Playing sound"); + numberOfPlayedSounds++; + } + + public void spawnParticles() { + LOGGER.info("Spawning particles"); + numberOfSpawnedParticles++; + } +} +``` + +下面我们展示虚拟机可用的指令。每个指令对于如何操作栈中的数据都有自己的语义。例如,增加指令,其取得栈顶的两个元素并把结果压入栈中。 + +```java +@AllArgsConstructor +@Getter +public enum Instruction { + + LITERAL(1), // e.g. "LITERAL 0", push 0 to stack + SET_HEALTH(2), // e.g. "SET_HEALTH", pop health and wizard number, call set health + SET_WISDOM(3), // e.g. "SET_WISDOM", pop wisdom and wizard number, call set wisdom + SET_AGILITY(4), // e.g. "SET_AGILITY", pop agility and wizard number, call set agility + PLAY_SOUND(5), // e.g. "PLAY_SOUND", pop value as wizard number, call play sound + SPAWN_PARTICLES(6), // e.g. "SPAWN_PARTICLES", pop value as wizard number, call spawn particles + GET_HEALTH(7), // e.g. "GET_HEALTH", pop value as wizard number, push wizard's health + GET_AGILITY(8), // e.g. "GET_AGILITY", pop value as wizard number, push wizard's agility + GET_WISDOM(9), // e.g. "GET_WISDOM", pop value as wizard number, push wizard's wisdom + ADD(10), // e.g. "ADD", pop 2 values, push their sum + DIVIDE(11); // e.g. "DIVIDE", pop 2 values, push their division + // ... +} +``` + +我们示例的核心是`虚拟机`类。 它将指令作为输入并执行它们以提供游戏对象行为。 + +```java +@Getter +@Slf4j +public class VirtualMachine { + + private final Stack stack = new Stack<>(); + + private final Wizard[] wizards = new Wizard[2]; + + public VirtualMachine() { + wizards[0] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32), + 0, 0); + wizards[1] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32), + 0, 0); + } + + public VirtualMachine(Wizard wizard1, Wizard wizard2) { + wizards[0] = wizard1; + wizards[1] = wizard2; + } + + public void execute(int[] bytecode) { + for (var i = 0; i < bytecode.length; i++) { + Instruction instruction = Instruction.getInstruction(bytecode[i]); + switch (instruction) { + case LITERAL: + // Read the next byte from the bytecode. + int value = bytecode[++i]; + // Push the next value to stack + stack.push(value); + break; + case SET_AGILITY: + var amount = stack.pop(); + var wizard = stack.pop(); + setAgility(wizard, amount); + break; + case SET_WISDOM: + amount = stack.pop(); + wizard = stack.pop(); + setWisdom(wizard, amount); + break; + case SET_HEALTH: + amount = stack.pop(); + wizard = stack.pop(); + setHealth(wizard, amount); + break; + case GET_HEALTH: + wizard = stack.pop(); + stack.push(getHealth(wizard)); + break; + case GET_AGILITY: + wizard = stack.pop(); + stack.push(getAgility(wizard)); + break; + case GET_WISDOM: + wizard = stack.pop(); + stack.push(getWisdom(wizard)); + break; + case ADD: + var a = stack.pop(); + var b = stack.pop(); + stack.push(a + b); + break; + case DIVIDE: + a = stack.pop(); + b = stack.pop(); + stack.push(b / a); + break; + case PLAY_SOUND: + wizard = stack.pop(); + getWizards()[wizard].playSound(); + break; + case SPAWN_PARTICLES: + wizard = stack.pop(); + getWizards()[wizard].spawnParticles(); + break; + default: + throw new IllegalArgumentException("Invalid instruction value"); + } + LOGGER.info("Executed " + instruction.name() + ", Stack contains " + getStack()); + } + } + + public void setHealth(int wizard, int amount) { + wizards[wizard].setHealth(amount); + } + // other setters -> + // ... +} +``` + +现在我们可以展示使用虚拟机的完整示例。 + +```java + public static void main(String[] args) { + + var vm = new VirtualMachine( + new Wizard(45, 7, 11, 0, 0), + new Wizard(36, 18, 8, 0, 0)); + + vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 0")); + vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 0")); + vm.execute(InstructionConverterUtil.convertToByteCode("GET_HEALTH")); + vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 0")); + vm.execute(InstructionConverterUtil.convertToByteCode("GET_AGILITY")); + vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 0")); + vm.execute(InstructionConverterUtil.convertToByteCode("GET_WISDOM")); + vm.execute(InstructionConverterUtil.convertToByteCode("ADD")); + vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 2")); + vm.execute(InstructionConverterUtil.convertToByteCode("DIVIDE")); + vm.execute(InstructionConverterUtil.convertToByteCode("ADD")); + vm.execute(InstructionConverterUtil.convertToByteCode("SET_HEALTH")); + } +``` + +下面是控制台输出。 + +``` +16:20:10.193 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0] +16:20:10.196 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 0] +16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_HEALTH, Stack contains [0, 45] +16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 0] +16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_AGILITY, Stack contains [0, 45, 7] +16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 7, 0] +16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_WISDOM, Stack contains [0, 45, 7, 11] +16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 45, 18] +16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 18, 2] +16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed DIVIDE, Stack contains [0, 45, 9] +16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 54] +16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed SET_HEALTH, Stack contains [] +``` + +## 类图 + +![alt text](../../../bytecode/etc/bytecode.urm.png "Bytecode class diagram") + +## 适用性 + + + +当您需要定义很多行为并且游戏的实现语言不合适时,请使用字节码模式,因为: + +* 它的等级太低,使得编程变得乏味或容易出错。 +* 由于编译时间慢或其他工具问题,迭代它需要很长时间。 +* 它有太多的信任。 如果您想确保定义的行为不会破坏游戏,您需要将其与代码库的其余部分进行沙箱化。 + +## 相关模式 + +* [Interpreter](https://java-design-patterns.com/patterns/interpreter/) + +## 鸣谢 + +* [Game programming patterns](http://gameprogrammingpatterns.com/bytecode.html) diff --git a/localization/zh/caching/README.md b/localization/zh/caching/README.md index 91b9a72bc..aa2c61941 100644 --- a/localization/zh/caching/README.md +++ b/localization/zh/caching/README.md @@ -2,7 +2,7 @@ layout: pattern title: Caching folder: caching -permalink: /patterns/caching/zh +permalink: /patterns/caching/ categories: Behavioral language: zh tags: @@ -14,7 +14,7 @@ tags: 为了避免昂贵的资源重新获取,方法是在资源使用后不立即释放资源。资源保留其身份,保留在某些快速访问的存储中,并被重新使用,以避免再次获取它们。 ## 类图 -![alt text](../../caching/etc/caching.png "Caching") +![alt text](../../../caching/etc/caching.png "Caching") ## 适用性 在以下情况下使用缓存模式 diff --git a/localization/zh/callback/README.md b/localization/zh/callback/README.md index d704a6f45..9665355fb 100644 --- a/localization/zh/callback/README.md +++ b/localization/zh/callback/README.md @@ -2,7 +2,7 @@ layout: pattern title: Callback folder: callback -permalink: /patterns/callback/zh +permalink: /patterns/callback/ categories: Idiom language: zh tags: @@ -69,7 +69,7 @@ public final class SimpleTask extends Task { task.executeWith(() -> LOGGER.info("I'm done now.")); ``` ## 类图 -![alt text](../../callback/etc/callback.png "Callback") +![alt text](../../../callback/etc/callback.png "Callback") ## 适用性 使用回调模式当 diff --git a/localization/zh/chain/README.md b/localization/zh/chain/README.md index b193b9cee..0262868a9 100644 --- a/localization/zh/chain/README.md +++ b/localization/zh/chain/README.md @@ -2,7 +2,7 @@ layout: pattern title: Chain of responsibility folder: chain -permalink: /patterns/chain/zh +permalink: /patterns/chain/ categories: Behavioral language: zh tags: @@ -139,7 +139,7 @@ king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); // Orc so ``` ## 类图 -![alt text](../../chain/etc/chain.urm.png "Chain of Responsibility class diagram") +![alt text](../../../chain/etc/chain.urm.png "Chain of Responsibility class diagram") ## 适用性 使用责任链模式当 diff --git a/localization/zh/circuit-breaker/README.md b/localization/zh/circuit-breaker/README.md index 1f2eaea76..e42d3940c 100644 --- a/localization/zh/circuit-breaker/README.md +++ b/localization/zh/circuit-breaker/README.md @@ -4,39 +4,45 @@ title: Circuit Breaker folder: circuit-breaker permalink: /patterns/circuit-breaker/ categories: Behavioral +language: zh tags: - Performance - Decoupling - Cloud distributed --- -## 含义 +## 意图 -以这样的方式(译者:指断路器方式)处理昂贵的远程服务调用,可以防止单个服务/组件的故障导致整个应用程序崩溃,同时我们可以尽快地进行服务重连。 +以这样一种方式处理昂贵的远程服务调用,即单个服务/组件的故障不会导致整个应用程序宕机,我们可以尽快重新连接到服务。 ## 解释 -现实世界案例 +真实世界例子 -> 设想一下,一个网络应用程序既有本地文件/图像,又有用于获取数据的远程服务。这些远程服务可能在某些时候是健康的、有反应的,也可能在某些时候由于各种原因而变得缓慢和无反应。因此,如果其中一个远程服务速度慢或不能成功响应,我们的应用程序将尝试使用多个线程/进程从远程服务中获取响应,很快所有的线程/进程都会挂起(也称为线程饥饿 thread starvation),从而导致我们整个 Web 应用程序崩溃。我们应该能够检测到这种情况,并向用户显示一个适当的信息,以便用户可以探索应用程序的其他部分,而不受远程服务故障的影响。同时,其他正常工作的服务应该保持运作,不受这次故障的影响。 +> 想象一个 Web 应用程序,它同时具有用于获取数据的本地文件/图像和远程服务。 这些远程服务有时可能健康且响应迅速,或者由于各种原因可能在某 个时间点变得缓慢和无响应。因此,如果其中一个远程服务缓慢或未成功响应,我们的应用程序将尝试使用多个线程/进程从远程服务获取响应,很快它们都会挂起(也称为 [线程饥饿][thread starvation](https://en.wikipedia.org/wiki/Starvation_(computer_science)))导致我们的整个 Web 应用程序崩溃。我们应该能够检测到这种情况并向用户显示适当的消息,以便他/她可以探索不受远程服务故障影响的应用程序的其他部分。 同时,其他正常工作的服务应保持正常运行,不受此故障的影响。 +> -简而言之 +通俗地说 -> 断路器允许优雅地处理失败的远程服务。当我们的应用程序的所有部分都高度解耦时,这种方式的效果会很好,一个组件的失败并不会导致其他部分停止工作。 +> 断路器允许优雅地处理失败的远程服务。当我们应用程序的所有部分彼此高度解耦时,它特别有用,一个组件的故障并不意味着其他部分将停止工作。 -维基百科的解释 +维基百科说 -> 断路器是现代软件开发中使用的一种设计模式。它用于检测故障,并封装了防止故障不断复发的逻辑,在维护期间,临时地处理外部系统故障或意外的系统问题。 +> 断路器是现代软件开发中使用的一种设计模式。 它用于检测故障并封装防止故障不断重复发生、维护期间、临时外部系统故障或意外系统困难的逻辑。 -## Programmatic Example +## 程序示例 -那么,这一切是如何实现的呢?考虑到上面的例子,我们将在一个简单的例子中模拟这个功能。一个监控服务(译者:下图的 Monitoring Service)模拟了网络应用,进行本地和远程调用。 +So, how does this all come together? With the above example in mind we will imitate the +functionality in a simple example. A monitoring service mimics the web app and makes both local and +remote calls. -该服务架构如下: +那么,这一切是如何结合在一起的呢? 记住上面的例子,我们将在一个简单的例子中模仿这个功能。 监控服务模仿 Web 应用程序并进行本地和远程调用。 -![alt text](../../circuit-breaker/etc/ServiceDiagram.png "Service Diagram") +服务架构如下: -终端用户(译者:上图的 End User)应用的代码如下: +![alt text](../../../circuit-breaker/etc/ServiceDiagram.png "Service Diagram") + +在代码方面,最终用户应用程序是: ```java @Slf4j @@ -61,44 +67,44 @@ public class App { var quickServiceCircuitBreaker = new DefaultCircuitBreaker(quickService, 3000, 2, 2000 * 1000 * 1000); - //Create an object of monitoring service which makes both local and remote calls + // 创建一个可以进行本地和远程调用的监控服务对象 var monitoringService = new MonitoringService(delayedServiceCircuitBreaker, quickServiceCircuitBreaker); - //Fetch response from local resource + // 获取本地资源 LOGGER.info(monitoringService.localResourceResponse()); - //Fetch response from delayed service 2 times, to meet the failure threshold + // 从延迟服务中获取响应 2 次,以满足失败阈值 LOGGER.info(monitoringService.delayedServiceResponse()); LOGGER.info(monitoringService.delayedServiceResponse()); - //Fetch current state of delayed service circuit breaker after crossing failure threshold limit - //which is OPEN now + // 在超过故障阈值限制后获取延迟服务断路器的当前状态 + // 现在是打开状态 LOGGER.info(delayedServiceCircuitBreaker.getState()); - //Meanwhile, the delayed service is down, fetch response from the healthy quick service + // 同时,延迟服务宕机,从健康快速服务获取响应 LOGGER.info(monitoringService.quickServiceResponse()); LOGGER.info(quickServiceCircuitBreaker.getState()); - //Wait for the delayed service to become responsive + // 等待延迟的服务响应 try { LOGGER.info("Waiting for delayed service to become responsive"); Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } - //Check the state of delayed circuit breaker, should be HALF_OPEN + // 检查延时断路器的状态,应该是HALF_OPEN LOGGER.info(delayedServiceCircuitBreaker.getState()); - //Fetch response from delayed service, which should be healthy by now + // 从延迟服务中获取响应,现在应该是健康的 LOGGER.info(monitoringService.delayedServiceResponse()); - //As successful response is fetched, it should be CLOSED again. + // 获取成功响应后,它的状态应该是关闭。 LOGGER.info(delayedServiceCircuitBreaker.getState()); } } ``` -监控服务代码(译者:上图的 monitoring service): +监控服务类: ```java public class MonitoringService { @@ -112,7 +118,7 @@ public class MonitoringService { this.quickService = quickService; } - //Assumption: Local service won't fail, no need to wrap it in a circuit breaker logic + // 假设:本地服务不会失败,无需将其包装在断路器逻辑中 public String localResourceResponse() { return "Local Service is working"; } @@ -144,7 +150,7 @@ public class MonitoringService { } } ``` -可以看出,它直接进行了获取本地资源的调用,但它把对远程(昂贵的)服务的调用包装在一个断路器对象中,这样可以防止出现如下故障: +可以看出,它直接调用获取本地资源,但它将对远程(昂贵)服务的调用包装在断路器对象中,防止故障如下: ```java public class DefaultCircuitBreaker implements CircuitBreaker { @@ -171,11 +177,11 @@ public class DefaultCircuitBreaker implements CircuitBreaker { DefaultCircuitBreaker(RemoteService serviceToCall, long timeout, int failureThreshold, long retryTimePeriod) { this.service = serviceToCall; - // We start in a closed state hoping that everything is fine + // 我们从关闭状态开始希望一切都是正常的 this.state = State.CLOSED; this.failureThreshold = failureThreshold; - // Timeout for the API request. - // Used to break the calls made to remote resource if it exceeds the limit + // API的超时时间. + // 用于在超过限制时中断对远程资源的调用 this.timeout = timeout; this.retryTimePeriod = retryTimePeriod; //An absurd amount of time in future which basically indicates the last failure never happened @@ -183,7 +189,7 @@ public class DefaultCircuitBreaker implements CircuitBreaker { this.failureCount = 0; } - // Reset everything to defaults + // 重置所有 @Override public void recordSuccess() { this.failureCount = 0; @@ -199,18 +205,18 @@ public class DefaultCircuitBreaker implements CircuitBreaker { this.lastFailureResponse = response; } - // Evaluate the current state based on failureThreshold, failureCount and lastFailureTime. + // 根据 failureThreshold、failureCount 和 lastFailureTime 评估当前状态。 protected void evaluateState() { if (failureCount >= failureThreshold) { //Then something is wrong with remote service if ((System.nanoTime() - lastFailureTime) > retryTimePeriod) { - //We have waited long enough and should try checking if service is up + // 我们已经等得够久了,应该尝试检查服务是否已启动 state = State.HALF_OPEN; } else { - //Service would still probably be down + // 服务可能仍会出现故障 state = State.OPEN; } } else { - //Everything is working fine + // 一切正常 state = State.CLOSED; } } @@ -253,16 +259,15 @@ public class DefaultCircuitBreaker implements CircuitBreaker { public String attemptRequest() throws RemoteServiceException { evaluateState(); if (state == State.OPEN) { - // return cached response if the circuit is in OPEN state + // 如果电路处于打开状态,则返回缓存的响应 return this.lastFailureResponse; } else { - // Make the API request if the circuit is not OPEN + // 如果电路未打开,则发出 API 请求 try { - //In a real application, this would be run in a thread and the timeout - //parameter of the circuit breaker would be utilized to know if service - //is working. Here, we simulate that based on server response itself + //在实际应用程序中,这将在线程中运行,并且将利用断路器的超时参数来了解服务 + // 是否正在工作。 在这里,我们根据服务器响应本身模拟 var response = service.call(); - // Yay!! the API responded fine. Let's reset everything. + // api 响应正常,重置所有。 recordSuccess(); return response; } catch (RemoteServiceException ex) { @@ -274,39 +279,39 @@ public class DefaultCircuitBreaker implements CircuitBreaker { } ``` -上述模式是如何防止失败的呢?让我们通过它所实现的这个有限状态机来了解。 +上述模式如何防止失败? 让我们通过它实现的这个有限状态机来理解。 -![alt text](../../circuit-breaker/etc/StateDiagram.png "State Diagram") +![alt text](../../../circuit-breaker/etc/StateDiagram.png "State Diagram") -- 我们用 `timeout`(超时)、 `failureThreshold` (失败阈值)、`retryTimePeriod`(重试时间周期) 参数初始化断路器对象 ,用于确定 API 的适应性。 -- 最初,断路器处于 `closed` 关闭状态,没有发生对 API 的远程调用。 -- 每次调用成功,我们就把状态重置为开始时的样子。 -- 如果失败的次数超过了一定的阈值(`failureThreshold`),断路器就会进入 `open` 开启状态,它的作用就像一个开启的电路,阻止远程服务的调用,从而节省资源。 -- 一旦我们超过重试时间周期(`retryTimePeriod`),断路器就会转到 `half-open` 半启用状态,并再次调用远程服务,检查服务是否正常,以便我们可以提供最新的响应内容。如果远程服务调用失败会使断路器回到 `open` 状态,并在重试超时后进行另一次尝试;如果远程服务调用成功则使断路器进入 `closed` 状态,这样一切又开始正常工作。 +- 我们使用某些参数初始化断路器对象:`timeout`、`failureThreshold` 和 `retryTimePeriod`,这有助于确定 API 的弹性。 +- 最初,我们处于“关闭”状态,没有发生对 API 的远程调用。 +- 每次调用成功时,我们都会将状态重置为开始时的状态。 +- 如果失败次数超过某个阈值,我们将进入“open”状态,这就像开路一样,阻止远程服务调用,从而节省资源。 (这里,我们从 API 返回名为 ```stale response``` 的响应) +- 一旦超过重试超时时间,我们就会进入“半开”状态并再次调用远程服务以检查服务是否正常工作,以便我们可以提供新鲜内容。 失败将其设置回“打开”状态,并在重试超时时间后进行另一次尝试,而成功将其设置为“关闭”状态,以便一切重新开始正常工作。 ## 类图 -![alt text](../../circuit-breaker/etc/circuit-breaker.urm.png "Circuit Breaker class diagram") +![alt text](../../../circuit-breaker/etc/circuit-breaker.urm.png "Circuit Breaker class diagram") -## 适用场景 +## 适用性 -在以下场景下,可以使用断路器模式: +在以下情况下使用断路器模式 -- 构建一个高可用的应用程序,某些些服务的失败不会导致整个应用程序的崩溃。 -- 构建一个持续运行(长期在线)的应用程序,以便其组件可以在不完全关闭的情况下进行升级。 +- 构建一个容错应用程序,其中某些服务的故障不应导致整个应用程序宕机。 +- 构建一个持续运行(永远在线)的应用程序,这样它的组件就可以在不完全关闭的情况下升级。 ## 相关模式 - [Retry Pattern](https://github.com/iluwatar/java-design-patterns/tree/master/retry) -## 现实案例 +## 真实世界例子 * [Spring Circuit Breaker module](https://spring.io/guides/gs/circuit-breaker) * [Netflix Hystrix API](https://github.com/Netflix/Hystrix) -## 引用 +## 鸣谢 * [Understanding Circuit Breaker Pattern](https://itnext.io/understand-circuitbreaker-design-pattern-with-simple-practical-example-92a752615b42) * [Martin Fowler on Circuit Breaker](https://martinfowler.com/bliki/CircuitBreaker.html) * [Fault tolerance in a high volume, distributed system](https://medium.com/netflix-techblog/fault-tolerance-in-a-high-volume-distributed-system-91ab4faae74a) -* [Circuit Breaker pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker) \ No newline at end of file +* [Circuit Breaker pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker) diff --git a/localization/zh/cloud-static-content-hosting/README.md b/localization/zh/cloud-static-content-hosting/README.md new file mode 100644 index 000000000..74bd385e0 --- /dev/null +++ b/localization/zh/cloud-static-content-hosting/README.md @@ -0,0 +1,134 @@ +--- +layout: pattern +title: Static Content Hosting +folder: cloud-static-content-hosting +permalink: /patterns/cloud-static-content-hosting/ +categories: Cloud +language: zh +tags: +- Cloud distributed +--- + +## 意图 + +将静态内容部署到基于云的存储服务,该服务可以将它们直接交付给客户端。 这可以减少对昂贵计算实例的需求。 + +## 解释 + +真实世界例子 + +> 全球性的营销网站(静态内容)需要快速的部署以开始吸引潜在的客户。为了将托管费用和维护成本降至最低,使用云托管存储服务和内容交付网络。 + +通俗地说 + +> 静态内容托管模式利用云原生存储服务来存储内容和全球内容交付网络,将其缓存在世界各地的多个数据中心。 在静态网站上,单个网页包含静态内容。 它们还可能包含客户端脚本,例如 Javascript。相比之下,动态网站依赖于服务器端处理,包括服务器端脚本,如 PHP、JSP 或 ASP.NET。 + +维基百科说 + +> 与由 Web 应用程序生成的动态网页相反,静态网页(有时称为平面网页或固定网页)是完全按照存储的方式传送到用户的网页浏览器的网页。静态网页适用于从不或很少需要更新的内容,尽管现代 +> Web 模板系统正在改变这一点。可以将大量静态页面作为文件进行维护,没有自动化工具(例如静态站点生成器)是不切实际的。 + +**示例** + +![alt text](../../../cloud-static-content-hosting/etc/static-content-hosting.png "Static Content Hosting") + +在这个例子中我们使用AWS S3创建一个静态网站,并利用 AWS Cloudfront 在全球范围内分发内容。 + +1. 首先你需要一个AWS账户,你可以在这个创建一个免费的:[AWS Free Tier](https://aws.amazon.com/free/free-tier/) + +2. 登陆 [AWS控制台](https://console.aws.amazon.com/console/home?nc2=h_ct&src=header-signin) + +3. 进入身份和接入管理服务 (IAM) . + +4. 创建一个仅具有此应用程序必要权限的IAM用户。 + + * 点击 `用户` + * 点击 `添加用户`. 选择你想要的 `用户名`, `接入类型`应该是 `编程式接入`. 点击 `下一步: 权限`. + * 选择 `直接附加已存在的策略`. 选择 `AmazonS3FullAccess` 和 `CloudFrontFullAccess`. Click `下一步: 标签`. + * 没有需要的标签, 所以直接点击 `下一步: 回顾`. + * 检查呈现的信息,没问题的话点击`创建用户` + * 完成这个示例所需要的`访问秘钥Id`和`访问秘钥密码`将会呈现在你面前,请妥善保管。 + * 点击 `关闭`. + +5. [安装AWS 命令行工具 (AWS CLI)](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv1.html) 来获得编程式访问AWS云。 + +6. 使用`aws configure`命令来配置AWS CLI [说明书](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config) + +7. 为web站点创建AWS S3 bucket。 注意S3 bucket名字必须要在全球范围内唯一。 + + + * 语法是 `aws s3 mb ` [说明书](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-buckets-creating) + * 比如 `aws s3 mb s3://my-static-website-jh34jsjmg` + * 使用列出现有存储桶的命令`aws s3 ls`验证存储桶是否已成功创建 + +8. 使用命令`aws s3 website`来配置bucket作为web站点。 [说明书](https://docs.aws.amazon.com/cli/latest/reference/s3/website.html). + + * 比如`aws s3 website s3://my-static-website-jh34jsjmg --index-document index.html --error-document error.html` + +9. 上传内容到bucket中。 + * 首先创建内容,至少包含`index.html`和`error.html`文档。 + * 上传内容到你的bucket中。 [说明书](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-copy) + * 比如`aws s3 cp index.html s3://my-static-website-jh34jsjmg` and `aws s3 cp error.html s3://my-static-website-jh34jsjmg` + +10. 然后我们需要设置bucket的策略以允许读取访问。 + + * 使用以下内容创建`policy.json`(注意需要将bucket名称替换为自己的)。 + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "PublicReadGetObject", + "Effect": "Allow", + "Principal": "*", + "Action": "s3:GetObject", + "Resource": "arn:aws:s3:::my-static-website-jh34jsjmg/*" + } + ] + } + ``` + + * 根据这些设置桶策略[说明书](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-bucket-policy.html) + * 比如 `aws s3api put-bucket-policy --bucket my-static-website-jh34jsjmg --policy file://policy.json` + +11. 使用浏览器测试web站点。 + + * web站点的URL格式是 `http://.s3-website-.amazonaws.com` + * 比如 这个站点创建在 `eu-west-1` 区域 ,名字是 `my-static-website-jh34jsjmg` 所以它可以通过 `http://my-static-website-jh34jsjmg.s3-website-eu-west-1.amazonaws.com`来访问。 + +12. 为web站点创建CloudFormation 分发。 + + * 语法文档在这里 [this reference](https://docs.aws.amazon.com/cli/latest/reference/cloudfront/create-distribution.html) + * 比如,最简单的方式是使用命令l `aws cloudfront create-distribution --origin-domain-name my-static-website-jh34jsjmg.s3.amazonaws.com --default-root-object index.html` + * 也支持JSON格式的配置 比如使用 `--distribution-config file://dist-config.json` 来传递分发的配置文件参数 + * 命令的舒勇将显示准确的分配配置项,包括包括可用于测试的生成的 CloudFront 域名,例如 `d2k3xwnaqa8nqx.cloudfront.net` + * CloudFormation 分发部署需要一些时间,但一旦完成,您的网站就会从全球各地的数据中心提供服务! + +13. 就是这样! 您已经实现了一个静态网站,其内容分发网络以闪电般的速度在世界各地提供服务。 + + * 要更新网站,您需要更新 S3 存储桶中的对象并使 CloudFront 分配中的对象无效 + * 要从 AWS CLI 执行此操作,请参阅 [this reference](https://docs.aws.amazon.com/cli/latest/reference/cloudfront/create-invalidation.html) + * 您可能想要做的进一步开发是通过 https 提供内容并为您的站点添加域名 + +## 适用性 + +当您想要执行以下操作时,请使用静态内容托管模式: + +* 最小化包含一些静态资源的网站和应用程序的托管成本。 +* 使用静态内容构建全球可用的网站 +* 监控网站流量、带宽使用、成本等。 + +## 典型用例 + +* 具有全球影响力的网站 +* 静态网站生成器生成的内容 +* 没有动态内容要求的网站 + +## 真实世界例子 + +* [Java Design Patterns web site](https://java-design-patterns.com) + +## 鸣谢 + +* [Static Content Hosting pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/static-content-hosting) diff --git a/localization/zh/collection-pipeline/README.md b/localization/zh/collection-pipeline/README.md index 87613100c..9077deae6 100644 --- a/localization/zh/collection-pipeline/README.md +++ b/localization/zh/collection-pipeline/README.md @@ -4,6 +4,7 @@ title: Collection Pipeline folder: collection-pipeline permalink: /patterns/collection-pipeline/ categories: Functional +language: zh tags: - Reactive --- @@ -13,7 +14,7 @@ tags: 在函数式编程中,可以通过一系列较小的模块化函数或操作来编排复杂的操作。这一系列函数被称为函数组合。当一个数据集合流经一个函数组合时,它就成为一个集合管道。函数组合和集合管道是函数式编程中经常使用的两种设计模式。 ## 类图 -![alt text](../../collection-pipeline/etc/collection-pipeline.png "Collection Pipeline") +![alt text](../../../collection-pipeline/etc/collection-pipeline.png "Collection Pipeline") ## 适用场景 在以下场景适用集合管道模式: diff --git a/localization/zh/command/README.md b/localization/zh/command/README.md index 201cb042c..a26533931 100644 --- a/localization/zh/command/README.md +++ b/localization/zh/command/README.md @@ -2,7 +2,7 @@ layout: pattern title: Command folder: command -permalink: /patterns/command/zh +permalink: /patterns/command/ categories: Behavioral language: zh tags: @@ -222,7 +222,7 @@ goblin.printStatus(); ``` ## 类图 -![alt text](../../command/etc/command.png "Command") +![alt text](../../../command/etc/command.png "Command") ## 适用性 使用命令模式当你想 diff --git a/localization/zh/composite-entity/README.md b/localization/zh/composite-entity/README.md index f38f30903..d15b64e39 100644 --- a/localization/zh/composite-entity/README.md +++ b/localization/zh/composite-entity/README.md @@ -4,6 +4,7 @@ title: Composite Entity folder: composite-entity permalink: /patterns/composite-entity/ categories: Structural +language: zh tags: - Enterprise Integration Pattern --- @@ -109,7 +110,7 @@ Arrays.stream(console.getData()).forEach(LOGGER::info); ## 类图 -![alt text](../../composite-entity/etc/composite_entity.urm.png "Composite Entity Pattern") +![alt text](../../../composite-entity/etc/composite_entity.urm.png "Composite Entity Pattern") ## 适用场景 diff --git a/localization/zh/composite/README.md b/localization/zh/composite/README.md index 6920190e2..4cfd29cb0 100644 --- a/localization/zh/composite/README.md +++ b/localization/zh/composite/README.md @@ -2,7 +2,7 @@ layout: pattern title: Composite folder: composite -permalink: /patterns/composite/zh +permalink: /patterns/composite/ categories: Structural language: zh tags: @@ -154,7 +154,7 @@ elfMessage.print(); // Much wind pours from your mouth. ## 类图 -![alt text](../../composite/etc/composite.urm.png "Composite class diagram") +![alt text](../../../composite/etc/composite.urm.png "Composite class diagram") ## 适用性 diff --git a/localization/zh/converter/README.md b/localization/zh/converter/README.md index 951a5c06b..1b8af5912 100644 --- a/localization/zh/converter/README.md +++ b/localization/zh/converter/README.md @@ -2,7 +2,7 @@ layout: pattern title: Converter folder: converter -permalink: /patterns/converter/zh +permalink: /patterns/converter/ categories: Creational language: zh tags: @@ -86,7 +86,7 @@ var user = userConverter.convertFromDto(dtoUser); ## 类图 -![alt text](../../converter/etc/converter.png "Converter Pattern") +![alt text](../../../converter/etc/converter.png "Converter Pattern") ## 适用性 diff --git a/localization/zh/dao/README.md b/localization/zh/dao/README.md index 388099773..c7e4614b6 100644 --- a/localization/zh/dao/README.md +++ b/localization/zh/dao/README.md @@ -2,7 +2,7 @@ layout: pattern title: Data Access Object folder: dao -permalink: /patterns/dao/zh +permalink: /patterns/dao/ categories: Architectural language: zh tags: @@ -149,7 +149,7 @@ customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@6ec8211c ## 类图 -![alt text](../../dao/etc/dao.png "Data Access Object") +![alt text](../../../dao/etc/dao.png "Data Access Object") ## 适用性 diff --git a/localization/zh/data-bus/README.md b/localization/zh/data-bus/README.md index 4eaa98914..d2fa730e7 100644 --- a/localization/zh/data-bus/README.md +++ b/localization/zh/data-bus/README.md @@ -3,8 +3,8 @@ layout: pattern title: Data Bus folder: data-bus permalink: /patterns/data-bus/ - categories: Architectural +language: zh tags: - Decoupling --- @@ -14,7 +14,7 @@ tags: 数据总线模式(译者:实际上,就是 Event-Bus 消息总线模式)允许在一个应用程序的组件之间收发消息/事件,而不需要这些组件相互感知,它们只需要知道所发送/接收的消息/事件的类型即可。 ## 类图 -![data bus pattern uml diagram](../../data-bus/etc/data-bus.urm.png "Data Bus pattern") +![data bus pattern uml diagram](../../../data-bus/etc/data-bus.urm.png "Data Bus pattern") ## 适用场景 可以在以下场景使用数据总线模式: diff --git a/localization/zh/data-mapper/README.md b/localization/zh/data-mapper/README.md index 4dc268fdb..a2c9ef188 100644 --- a/localization/zh/data-mapper/README.md +++ b/localization/zh/data-mapper/README.md @@ -4,6 +4,7 @@ title: Data Mapper folder: data-mapper permalink: /patterns/data-mapper/ categories: Architectural +language: zh tags: - Decoupling --- @@ -12,7 +13,7 @@ tags: 一个用于在持久化对象和数据库之间传输数据的映射器,同时保持它们之间和映射器本身的独立性。 ## 类图 -![alt text](../../data-mapper/etc/data-mapper.png "Data Mapper") +![alt text](../../../data-mapper/etc/data-mapper.png "Data Mapper") ## 适用场景 数据映射器适用于以下场景: diff --git a/localization/zh/data-transfer-object/README.md b/localization/zh/data-transfer-object/README.md index 36ed5cc7b..c9e938fde 100644 --- a/localization/zh/data-transfer-object/README.md +++ b/localization/zh/data-transfer-object/README.md @@ -2,7 +2,7 @@ layout: pattern title: Data Transfer Object folder: data-transfer-object -permalink: /patterns/data-transfer-object/zh +permalink: /patterns/data-transfer-object/ categories: Architectural language: zh tags: @@ -94,7 +94,7 @@ public class CustomerResource { ## 类图 -![alt text](../../data-transfer-object/etc/data-transfer-object.urm.png "data-transfer-object") +![alt text](../../../data-transfer-object/etc/data-transfer-object.urm.png "data-transfer-object") ## 适用性 diff --git a/localization/zh/decorator/README.md b/localization/zh/decorator/README.md index b7280cce7..dcb1ca8fe 100644 --- a/localization/zh/decorator/README.md +++ b/localization/zh/decorator/README.md @@ -2,7 +2,7 @@ layout: pattern title: Decorator folder: decorator -permalink: /patterns/decorator/zh +permalink: /patterns/decorator/ categories: Structural language: zh tags: @@ -106,7 +106,7 @@ clubbedTroll.fleeBattle(); // The troll shrieks in horror and runs away! ``` ## 类图 -![alt text](../../decorator/etc/decorator.urm.png "Decorator pattern class diagram") +![alt text](../../../decorator/etc/decorator.urm.png "Decorator pattern class diagram") ## 适用性 使用装饰者 diff --git a/localization/zh/delegation/README.md b/localization/zh/delegation/README.md index 1a7f418a0..40fb62024 100644 --- a/localization/zh/delegation/README.md +++ b/localization/zh/delegation/README.md @@ -2,7 +2,7 @@ layout: pattern title: Delegation folder: delegation -permalink: /patterns/delegation/zh +permalink: /patterns/delegation/ categories: Structural language: zh tags: @@ -16,7 +16,7 @@ tags: 它是一种让对象将某种行为向外部表达,但实际上将实现该行为的责任委托给关联对象的技术。 ## 类图 -![alt text](../../delegation/etc/delegation.png "Delegate") +![alt text](../../../delegation/etc/delegation.png "Delegate") ## 适用性 使用委托模式以实现以下目的 diff --git a/localization/zh/dependency-injection/README.md b/localization/zh/dependency-injection/README.md index 2ce1ef6dd..16262fa86 100644 --- a/localization/zh/dependency-injection/README.md +++ b/localization/zh/dependency-injection/README.md @@ -2,7 +2,7 @@ layout: pattern title: Dependency Injection folder: dependency-injection -permalink: /patterns/dependency-injection/zh +permalink: /patterns/dependency-injection/ categories: Creational language: zh tags: @@ -84,7 +84,7 @@ public class AdvancedWizard implements Wizard { ## 类图 -![alt text](../../dependency-injection/etc/dependency-injection.png "Dependency Injection") +![alt text](../../../dependency-injection/etc/dependency-injection.png "Dependency Injection") ## 适用性 diff --git a/localization/zh/dirty-flag/README.md b/localization/zh/dirty-flag/README.md index 2ef9308eb..12bd1c067 100644 --- a/localization/zh/dirty-flag/README.md +++ b/localization/zh/dirty-flag/README.md @@ -2,7 +2,7 @@ layout: pattern title: Dirty Flag folder: dirty-flag -permalink: /patterns/dirty-flag/zh +permalink: /patterns/dirty-flag/ categories: Behavioral language: zh tags: @@ -17,7 +17,7 @@ tags: 避免昂贵资源的重新获取。资源保留其身份,保留在某些快速访问的存储中,并被重新使用以避免再次获取它们。 ## 类图 -![alt text](../../dirty-flag/etc/dirty-flag.png "Dirty Flag") +![alt text](../../../dirty-flag/etc/dirty-flag.png "Dirty Flag") ## 适用性 在以下情况下使用脏标志模式 diff --git a/localization/zh/double-checked-locking/README.md b/localization/zh/double-checked-locking/README.md index 5a8a6312d..8a989b9f5 100644 --- a/localization/zh/double-checked-locking/README.md +++ b/localization/zh/double-checked-locking/README.md @@ -4,6 +4,7 @@ title: Double Checked Locking folder: double-checked-locking permalink: /patterns/double-checked-locking/ categories: Idiom +language: zh tags: - Performance --- @@ -12,7 +13,7 @@ tags: 通过先测试锁定标准("锁提示")而不实际获取锁的方式来减少获取锁的开销。只有当锁定标准检查表明需要锁定时,才进行实际的锁定逻辑。 ## 类图 -![alt text](../../double-checked-locking/etc/double_checked_locking_1.png "Double Checked Locking") +![alt text](../../../double-checked-locking/etc/double_checked_locking_1.png "Double Checked Locking") ## 适用场景 在以下场景适合使用双重锁检查模式: diff --git a/localization/zh/facade/README.md b/localization/zh/facade/README.md index 9bd36c95a..b49a7abd9 100644 --- a/localization/zh/facade/README.md +++ b/localization/zh/facade/README.md @@ -2,7 +2,7 @@ layout: pattern title: Facade folder: facade -permalink: /patterns/facade/zh +permalink: /patterns/facade/ categories: Structural language: zh tags: @@ -189,7 +189,7 @@ facade.endDay(); ``` ## 类图 -![alt text](../../facade/etc/facade.urm.png "Facade pattern class diagram") +![alt text](../../../facade/etc/facade.urm.png "Facade pattern class diagram") ## 适用性 使用外观模式当 diff --git a/localization/zh/factory-kit/README.md b/localization/zh/factory-kit/README.md index 4f4b58b59..c5c7a9884 100644 --- a/localization/zh/factory-kit/README.md +++ b/localization/zh/factory-kit/README.md @@ -4,6 +4,7 @@ title: Factory Kit folder: factory-kit permalink: /patterns/factory-kit/ categories: Creational +language: zh tags: - Extensibility --- @@ -12,7 +13,7 @@ tags: 使用分离的构建器和工厂接口来定义一个不可变内容的工厂。 ## 类图 -![alt text](../../factory-kit/etc/factory-kit.png "Factory Kit") +![alt text](../../../factory-kit/etc/factory-kit.png "Factory Kit") ## 适用场景 工厂套件模式适用于与以下场景: diff --git a/localization/zh/factory-method/README.md b/localization/zh/factory-method/README.md index fcb0c2b01..123721ba1 100644 --- a/localization/zh/factory-method/README.md +++ b/localization/zh/factory-method/README.md @@ -2,7 +2,7 @@ layout: pattern title: Factory Method folder: factory-method -permalink: /patterns/factory-method/zh +permalink: /patterns/factory-method/ categories: Creational language: zh tags: @@ -63,7 +63,7 @@ blacksmith.manufactureWeapon(WeaponType.AXE); ``` ## 类图 -![alt text](../../factory-method/etc/factory-method.urm.png "Factory Method pattern class diagram") +![alt text](../../../factory-method/etc/factory-method.urm.png "Factory Method pattern class diagram") ## 适用性 使用工厂方法模式当 diff --git a/localization/zh/factory/README.md b/localization/zh/factory/README.md index 414f1e7a9..19985c6f7 100644 --- a/localization/zh/factory/README.md +++ b/localization/zh/factory/README.md @@ -4,6 +4,7 @@ title: Factory folder: factory permalink: /patterns/factory/ categories: Creational +language: zh tags: - Gang of Four --- @@ -108,7 +109,7 @@ This is Ferrari. ## 类图 -![alt text](../../factory/etc/factory.urm.png "Factory pattern class diagram") +![alt text](../../../factory/etc/factory.urm.png "Factory pattern class diagram") ## 适用场景 diff --git a/localization/zh/interpreter/README.md b/localization/zh/interpreter/README.md index feafff9bd..126a70b79 100644 --- a/localization/zh/interpreter/README.md +++ b/localization/zh/interpreter/README.md @@ -2,7 +2,7 @@ layout: pattern title: Interpreter folder: interpreter -permalink: /patterns/interpreter/zh +permalink: /patterns/interpreter/ categories: Behavioral language: zh tags: @@ -13,7 +13,7 @@ tags: 给定一种语言,请定义其语法的表示形式,以及使用该表示形式来解释该语言中的句子的解释器。 ## 类图 -![alt text](../../interpreter/etc/interpreter_1.png "Interpreter") +![alt text](../../../interpreter/etc/interpreter_1.png "Interpreter") ## 适用性 有一种要解释的语言时,请使用解释器模式,并且可以将语言中的语句表示为抽象语法树。解释器模式在以下情况下效果最佳 diff --git a/localization/zh/iterator/README.md b/localization/zh/iterator/README.md index 257693a32..c7b6f0fad 100644 --- a/localization/zh/iterator/README.md +++ b/localization/zh/iterator/README.md @@ -2,7 +2,7 @@ layout: pattern title: Iterator folder: iterator -permalink: /patterns/iterator/zh +permalink: /patterns/iterator/ categories: Behavioral language: zh tags: @@ -115,7 +115,7 @@ while (itemIterator.hasNext()) { ``` ## 类图 -![alt text](../../iterator/etc/iterator_1.png "Iterator") +![alt text](../../../iterator/etc/iterator_1.png "Iterator") ## 适用性 以下情况使用迭代器模式 diff --git a/localization/zh/observer/README.md b/localization/zh/observer/README.md index 976e2da2f..e2417d4ff 100644 --- a/localization/zh/observer/README.md +++ b/localization/zh/observer/README.md @@ -2,7 +2,7 @@ layout: pattern title: Observer folder: observer -permalink: /patterns/observer/zh +permalink: /patterns/observer/ categories: Behavioral language: zh tags: @@ -129,7 +129,7 @@ public class Weather { ``` ## Class diagram -![alt text](../../observer/etc/observer.png "Observer") +![alt text](../../../observer/etc/observer.png "Observer") ## 应用 在下面任何一种情况下都可以使用观察者模式 diff --git a/localization/zh/private-class-data/README.md b/localization/zh/private-class-data/README.md index 76accc16c..6eb32a70f 100644 --- a/localization/zh/private-class-data/README.md +++ b/localization/zh/private-class-data/README.md @@ -2,7 +2,7 @@ layout: pattern title: Private Class Data folder: private-class-data -permalink: /patterns/private-class-data/zh +permalink: /patterns/private-class-data/ categories: Idiom language: zh tags: @@ -120,7 +120,7 @@ immutableStew.mix(); // Mixing the immutable stew we find: 2 potatoes, 4 carrot ## 类图 -![alt text](../../private-class-data/etc/private-class-data.png "Private Class Data") +![alt text](../../../private-class-data/etc/private-class-data.png "Private Class Data") ## 适用性 diff --git a/localization/zh/producer-consumer/README.md b/localization/zh/producer-consumer/README.md index 4cced03ba..8cda270b1 100644 --- a/localization/zh/producer-consumer/README.md +++ b/localization/zh/producer-consumer/README.md @@ -2,7 +2,7 @@ layout: pattern title: Producer Consumer folder: producer-consumer -permalink: /patterns/producer-consumer/zh +permalink: /patterns/producer-consumer/ categories: Concurrency language: zh tags: @@ -13,7 +13,7 @@ tags: 生产者消费者设计模式是一种经典的并发模式,通过将工作与执行工作任务分开来减少生产者与消费者之间的耦合。 ## 类图 -![alt text](../../producer-consumer/etc/producer-consumer.png "Producer Consumer") +![alt text](../../../producer-consumer/etc/producer-consumer.png "Producer Consumer") ## 适用性 在以下情况下使用生产者消费者 diff --git a/localization/zh/proxy/README.md b/localization/zh/proxy/README.md index 2ba8afe73..808b16505 100644 --- a/localization/zh/proxy/README.md +++ b/localization/zh/proxy/README.md @@ -2,7 +2,7 @@ layout: pattern title: Proxy folder: proxy -permalink: /patterns/proxy/zh +permalink: /patterns/proxy/ categories: Structural language: zh tags: @@ -123,7 +123,7 @@ Brown wizard is not allowed to enter! ## 类图 -![alt text](../../proxy/etc/proxy.urm.png "Proxy pattern class diagram") +![alt text](../../../proxy/etc/proxy.urm.png "Proxy pattern class diagram") ## 适用性 diff --git a/localization/zh/sharding/README.md b/localization/zh/sharding/README.md index b4b6073e0..71552bc48 100644 --- a/localization/zh/sharding/README.md +++ b/localization/zh/sharding/README.md @@ -4,6 +4,7 @@ title: Sharding folder: sharding permalink: /patterns/sharding/ categories: Behavioral +language: zh tags: - Performance - Cloud distributed @@ -15,7 +16,7 @@ tags: 一个分片本身就是一个数据存储(它可以包含许多不同类型的实体的数据),运行在作为存储节点的服务器上。 ## 类图 -![alt text](../../sharding/etc/sharding.urm.png "Sharding pattern class diagram") +![alt text](../../../sharding/etc/sharding.urm.png "Sharding pattern class diagram") ## 适用场景 这种设计模式提供了一下的好处: diff --git a/localization/zh/state/README.md b/localization/zh/state/README.md index 2ed8773c6..ba2d555d2 100644 --- a/localization/zh/state/README.md +++ b/localization/zh/state/README.md @@ -2,7 +2,7 @@ layout: pattern title: State folder: state -permalink: /patterns/state/zh +permalink: /patterns/state/ categories: Behavioral language: zh tags: @@ -135,7 +135,7 @@ public class Mammoth { ``` ## 类图 -![alt text](../../state/etc/state_urm.png "State") +![alt text](../../../state/etc/state_urm.png "State") ## 适用性 diff --git a/localization/zh/strategy/README.md b/localization/zh/strategy/README.md index 1ff49ef46..aee867b0a 100644 --- a/localization/zh/strategy/README.md +++ b/localization/zh/strategy/README.md @@ -2,7 +2,7 @@ layout: pattern title: Strategy folder: strategy -permalink: /patterns/strategy/zh +permalink: /patterns/strategy/ categories: Behavioral language: zh tags: @@ -112,7 +112,7 @@ public class DragonSlayer { ``` ## 类图 -![alt text](../../strategy/etc/strategy_1.png "Strategy") +![alt text](../../../strategy/etc/strategy_urm.png "Strategy") ## 应用 使用策略模式当 diff --git a/localization/zh/template-method/README.md b/localization/zh/template-method/README.md index 9fa5fbbe3..6bd40f032 100644 --- a/localization/zh/template-method/README.md +++ b/localization/zh/template-method/README.md @@ -2,7 +2,7 @@ layout: pattern title: Template method folder: template-method -permalink: /patterns/template-method/zh +permalink: /patterns/template-method/ categories: Behavioral language: zh tags: @@ -119,7 +119,7 @@ public class HalflingThief { ``` ## 类图 -![alt text](../../template-method/etc/template_method_urm.png "Template Method") +![alt text](../../../template-method/etc/template_method_urm.png "Template Method") ## 适用性 diff --git a/localization/zh/version-number/README.md b/localization/zh/version-number/README.md index ef447a123..f5985ab66 100644 --- a/localization/zh/version-number/README.md +++ b/localization/zh/version-number/README.md @@ -2,13 +2,13 @@ layout: pattern title: Version Number folder: versionnumber -permalink: /patterns/versionnumber/zh +permalink: /patterns/versionnumber/ description: Entity versioning with version number -language: zh categories: - Concurrency +language: zh tags: - Data access - Microservices @@ -135,7 +135,7 @@ Exception: Tried to update stale version 0 while actual version is 1 ## 类图 -![alt text](../../version-number/etc/version-number.urm.png "Version Number pattern class diagram") +![alt text](../../../version-number/etc/version-number.urm.png "Version Number pattern class diagram") ## 适用性 diff --git a/localization/zh/visitor/README.md b/localization/zh/visitor/README.md index b12a6f19a..2454032f0 100644 --- a/localization/zh/visitor/README.md +++ b/localization/zh/visitor/README.md @@ -2,7 +2,7 @@ layout: pattern title: Visitor folder: visitor -permalink: /patterns/visitor/zh +permalink: /patterns/visitor/ categories: Behavioral language: zh tags: @@ -201,7 +201,7 @@ Good to see you commander ## Class diagram -![alt text](../../visitor/etc/visitor_1.png "Visitor") +![alt text](../../../visitor/etc/visitor_1.png "Visitor") ## 适用性