From 38d28870f2ebc9c65f29799d094e7d9cd0fbd233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sat, 14 Oct 2023 11:16:02 +0300 Subject: [PATCH 01/26] fix: fix crtp markdown syntax --- crtp/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crtp/README.md b/crtp/README.md index 89f0720a8ebe..67627f44da7f 100644 --- a/crtp/README.md +++ b/crtp/README.md @@ -134,5 +134,5 @@ Use the Curiously Recurring Template Pattern when ## Credits -* [How do I decrypt "Enum>"?](http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ106) +* [How do I decrypt "Enum>"?](http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ106) * Chapter 5 Generics, Item 30 in [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb) From 1bea90ed9ca075bdd3efdcdfdead3444984585be Mon Sep 17 00:00:00 2001 From: kongleong86 Date: Sat, 14 Oct 2023 11:58:15 +0100 Subject: [PATCH 02/26] refactor: Remove deprecated method of newInstance (#2594) --- .../java/com/iluwatar/front/controller/FrontController.java | 2 +- role-object/src/main/java/com/iluwatar/roleobject/Role.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java b/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java index 21a49f625e5c..995f917b3fd5 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java @@ -38,7 +38,7 @@ public void handleRequest(String request) { private Command getCommand(String request) { var commandClass = getCommandClass(request); try { - return (Command) commandClass.newInstance(); + return (Command) commandClass.getDeclaredConstructor().newInstance(); } catch (Exception e) { throw new ApplicationException(e); } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/Role.java b/role-object/src/main/java/com/iluwatar/roleobject/Role.java index ef808c15dd6b..de216b0d7a07 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/Role.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/Role.java @@ -24,6 +24,7 @@ */ package com.iluwatar.roleobject; +import java.lang.reflect.InvocationTargetException; import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,8 +51,8 @@ public enum Role { public Optional instance() { var typeCst = this.typeCst; try { - return (Optional) Optional.of(typeCst.newInstance()); - } catch (InstantiationException | IllegalAccessException e) { + return (Optional) Optional.of(typeCst.getDeclaredConstructor().newInstance()); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { logger.error("error creating an object", e); } return Optional.empty(); From ffbcbdcb33bcd739fbfb58b70faab5cc26a44954 Mon Sep 17 00:00:00 2001 From: Allagadda Sai Upendranath Date: Sat, 14 Oct 2023 16:32:05 +0530 Subject: [PATCH 03/26] docs: Update README.md of typeObjectpattern (#2596) Fixes #2266 Explanation for Type-Object --- typeobjectpattern/README.md | 59 +++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/typeobjectpattern/README.md b/typeobjectpattern/README.md index f75e217d2616..742792a8f423 100644 --- a/typeobjectpattern/README.md +++ b/typeobjectpattern/README.md @@ -7,17 +7,63 @@ tag: - Extensibility --- +# Type-Object Pattern in Java + +## Explanation + +In Java, the Type-Object pattern is a design pattern that encapsulates type information in an object. This pattern is particularly useful when dealing with multiple objects of the same kind, and there is a need to add new types without altering existing code. + ## Intent As explained in the book Game Programming Patterns by Robert Nystrom, type object pattern helps in > Allowing flexible creation of new “classes” by creating a single class, each instance of which represents a different type of object -## Explanation -Say, we are working on a game which has a hero and many monsters which are going to attack the hero. These monsters have certain attributes like attack, points etc. and come in different 'breeds' like zombie or ogres. The obvious answer is to have a base Monster class which has some fields and methods, which may be overriden by subclasses like the Zombie or Ogre class. But as we continue to build the game, there may be more and more breeds of monsters added and certain attributes may need to be changed in the existing monsters too. The OOP solution of inheriting from the base class would not be an efficient method in this case. +## Real World Example +Let's consider a real-world example. Say, we are working on a game which has a hero and many monsters which are going to attack the hero. These monsters have certain attributes like attack, points etc. and come in different 'breeds' like zombie or ogres. The obvious answer is to have a base Monster class which has some fields and methods, which may be overriden by subclasses like the Zombie or Ogre class. But as we continue to build the game, there may be more and more breeds of monsters added and certain attributes may need to be changed in the existing monsters too. The OOP solution of inheriting from the base class would not be an efficient method in this case. Using the type-object pattern, instead of creating many classes inheriting from a base class, we have 1 class with a field which represents the 'type' of object. This makes the code cleaner and object instantiation also becomes as easy as parsing a json file with the object properties. -## Class diagram -![alt text](./etc/typeobjectpattern.urm.png "Type-Object pattern class diagram") +## In Plain Words + +The Type-Object pattern in Java is a method to encapsulate type-specific properties and behaviors within an object. This design pattern facilitates the addition of new types without necessitating changes to existing code, thereby enhancing codebase expansion and maintenance. + +## Wikipedia Says + +While there isn't a specific Wikipedia entry for the Type-Object pattern, it is a commonly used technique in object-oriented programming. This pattern assists in managing objects that share similar characteristics but have different values for those characteristics. It finds widespread use in game development, where numerous types of objects (like enemies) share common behavior but have different properties. + +## Programmatic Example + +Consider an example involving different types of enemies in a game. Each enemy type has distinct properties like speed, health, and damage. + +```java +public class EnemyType { + private String name; + private int speed; + private int health; + private int damage; + + public EnemyType(String name, int speed, int health, int damage) { + this.name = name; + this.speed = speed; + this.health = health; + this.damage = damage; + } + + // getters and setters +} + +public class Enemy { + private EnemyType type; + + // Encapsulating type information in an object + public Enemy(EnemyType type) { + this.type = type; + } + + // other methods +} +``` + +In the above example, `EnemyType` encapsulates type-specific properties (name, speed, health, damage), and `Enemy` uses an instance of `EnemyType` to define its type. This way, you can add as many enemy types as you want without modifying the `Enemy` class. ## Applicability This pattern can be used when: @@ -25,7 +71,10 @@ This pattern can be used when: * We don’t know what types we will need up front. * We want to be able to modify or add new types without having to recompile or change code. * Only difference between the different 'types' of objects is the data, not the behaviour. - + +## Another example with class diagram +![alt text](./etc/typeobjectpattern.urm.png "Type-Object pattern class diagram") + ## Credits * [Game Programming Patterns - Type Object](http://gameprogrammingpatterns.com/type-object.html) From d838f3491bb87776dff0f7a18631b1ab5f32a434 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 14 Oct 2023 14:02:57 +0300 Subject: [PATCH 04/26] docs: add Upendra-Allagadda as a contributor for doc (#2647) * 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 | 11 ++++++++++- README.md | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 806d0f4d91e1..e29445b04b8d 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2641,7 +2641,16 @@ "contributions": [ "doc", "code" - ] + ] + }, + { + "login": "Upendra-Allagadda", + "name": "Allagadda Sai Upendranath", + "avatar_url": "https://avatars.githubusercontent.com/u/25962010?v=4", + "profile": "https://github.com/Upendra-Allagadda", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index d64f84195251..2ba873086f99 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-289-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-291-orange.svg?style=flat-square)](#contributors-)
@@ -448,6 +448,7 @@ This project is licensed under the terms of the MIT license. Sanchit Bansal
Sanchit Bansal

📖 Md Saiful Islam
Md Saiful Islam

📖 Antonio Addeo
Antonio Addeo

📖 💻 + Allagadda Sai Upendranath
Allagadda Sai Upendranath

📖 From d247395440eb1f8ae5e57daf496debcdd54e67e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Oct 2023 14:08:00 +0300 Subject: [PATCH 05/26] build(deps): bump com.mycila:license-maven-plugin from 4.2 to 4.3 (#2603) Bumps com.mycila:license-maven-plugin from 4.2 to 4.3. --- updated-dependencies: - dependency-name: com.mycila:license-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 736aa6ddb55d..4169976ff444 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ 1.1.0 3.1.2 3.3.0 - 4.2 + 4.3 2.1.1 https://sonarcloud.io From dd040baa4bf61cd0fdf54ef32faa3b688d229b63 Mon Sep 17 00:00:00 2001 From: Matheus Braga Date: Sat, 14 Oct 2023 08:08:58 -0300 Subject: [PATCH 06/26] translation: Translate Factory pattern README to portuguese. (#2602) --- localization/pt/factory/README.md | 141 ++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 localization/pt/factory/README.md diff --git a/localization/pt/factory/README.md b/localization/pt/factory/README.md new file mode 100644 index 000000000000..296c1b758b0c --- /dev/null +++ b/localization/pt/factory/README.md @@ -0,0 +1,141 @@ +--- +title: Factory +category: Creational +language: pt +tag: + - Gang of Four +--- + +## Também conhecido como + +* Simple Factory +* Static Factory Method + +## Propósito + +Fornecer um método estático encapsulado em uma classe conhecida como factory, para ocultar a lógica +de implementação e fazer com que o código do cliente se preocupe apenas com sua utilização em vez de +inicializar novos objetos. + +## Explicação + +Exemplo de mundo real + +> Imagine um alquimista que está prestes a fabricar moedas. O alquimista deve ser capaz de produzir +> moedas de ouro e cobre, e a alternância entre a fabricação destas deve ser possível sem a necessidade +> de modificar o código fonte. O padrão factory torna isso possível fornecendo um método construtor estático +> que pode ser chamado com parâmetros relevantes. + +Wikipedia diz + +> Factory é um objeto para a criação de outros objetos - formalmente uma factory é uma função ou método +> que retorna objetos de protótipos ou classes variadas. + +**Exemplo de programação** + +Temos uma interface `Coin` e duas implementações `GoldCoin` e `CopperCoin`. + +```java +public interface Coin { + String getDescription(); +} + +public class GoldCoin implements Coin { + + static final String DESCRIPTION = "This is a gold coin."; + + @Override + public String getDescription() { + return DESCRIPTION; + } +} + +public class CopperCoin implements Coin { + + static final String DESCRIPTION = "This is a copper coin."; + + @Override + public String getDescription() { + return DESCRIPTION; + } +} +``` + +O enum abaixo representa os tipos de moedas que suportamos (`GoldCoin` e `CopperCoin`). + +```java +@RequiredArgsConstructor +@Getter +public enum CoinType { + + COPPER(CopperCoin::new), + GOLD(GoldCoin::new); + + private final Supplier constructor; +} +``` + +Então temos o método estático `getCoin` para criar objetos de moeda encapsulados na classe factory +`CoinFactory`. + +```java +public class CoinFactory { + + public static Coin getCoin(CoinType type) { + return type.getConstructor().get(); + } +} +``` + +Agora no código cliente podemos criar diferentes tipos de moedas usando a classe factory. + +```java +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()); +``` + +Saída do programa: + +```java +The alchemist begins his work. +This is a copper coin. +This is a gold coin. +``` + +## Diagrama de classes + +![alt text](./etc/factory.urm.png "Diagrama de classes do padrão Factory") + +## Aplicabilidade + +Utilize o padrão factory quando a preocupação é apenas em criar o objeto, e não como criar +e gerenciá-lo. + +Prós + +* Permite manter a criação de todos os objetos em um só lugar e evita espalhar a palavra-chave 'new' pela base de código. +* Permite escrever código desacoplado. Algumas de suas principais vantagens incluem uma melhor testabilidade, código fácil de entender, componentes substituíveis, escalabilidade e funcionalidades isoladas. + +Contras + +* O código se torna mais complicado do que deveria. + +## Usos conhecidos + +* [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) (retorna objetos singleton diferentes, dependendo do protocolo) +* [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--) e outros métodos parecidos. + +## Padrões relacionados + +* [Factory Method](https://java-design-patterns.com/patterns/factory-method/) +* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/) +* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/) + From cbe84b3b9d2fcda1bd1ca0ccef3ce836d522b6d8 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 14 Oct 2023 14:09:52 +0300 Subject: [PATCH 07/26] docs: add mathbraga as a contributor for translation (#2648) * 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 e29445b04b8d..5939fba438fd 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2651,6 +2651,15 @@ "contributions": [ "doc" ] + }, + { + "login": "mathbraga", + "name": "Matheus Braga", + "avatar_url": "https://avatars.githubusercontent.com/u/31048764?v=4", + "profile": "https://www.linkedin.com/in/mobraga/", + "contributions": [ + "translation" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 2ba873086f99..a5476f639952 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-291-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-292-orange.svg?style=flat-square)](#contributors-)
@@ -449,6 +449,7 @@ This project is licensed under the terms of the MIT license. Md Saiful Islam
Md Saiful Islam

📖 Antonio Addeo
Antonio Addeo

📖 💻 Allagadda Sai Upendranath
Allagadda Sai Upendranath

📖 + Matheus Braga
Matheus Braga

🌍 From 07663ce2bdd46ca4697307068b9eb0d4c8888ead Mon Sep 17 00:00:00 2001 From: Matheus Braga Date: Sat, 14 Oct 2023 08:11:10 -0300 Subject: [PATCH 08/26] docs: Fix typos in factory pattern README (#2605) --- factory/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/factory/README.md b/factory/README.md index f6fa1b5a033a..ed841bd0e2da 100644 --- a/factory/README.md +++ b/factory/README.md @@ -60,7 +60,7 @@ public class CopperCoin implements Coin { } ``` -Enumeration above represents types of coins that we support (`GoldCoin` and `CopperCoin`). +Enumeration below represents types of coins that we support (`GoldCoin` and `CopperCoin`). ```java @RequiredArgsConstructor @@ -110,7 +110,7 @@ This is a gold coin. ## Applicability -Use the 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 an object, not how to create and manage it. Pros From 6d21e2745f6f3dd53cdc9cda594cab2e07682a3b Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 14 Oct 2023 14:11:59 +0300 Subject: [PATCH 09/26] docs: add mathbraga as a contributor for doc (#2649) * 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 | 3 ++- README.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 5939fba438fd..87fe385d7535 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2658,7 +2658,8 @@ "avatar_url": "https://avatars.githubusercontent.com/u/31048764?v=4", "profile": "https://www.linkedin.com/in/mobraga/", "contributions": [ - "translation" + "translation", + "doc" ] } ], diff --git a/README.md b/README.md index a5476f639952..08d7edc48364 100644 --- a/README.md +++ b/README.md @@ -449,7 +449,7 @@ This project is licensed under the terms of the MIT license. Md Saiful Islam
Md Saiful Islam

📖 Antonio Addeo
Antonio Addeo

📖 💻 Allagadda Sai Upendranath
Allagadda Sai Upendranath

📖 - Matheus Braga
Matheus Braga

🌍 + Matheus Braga
Matheus Braga

🌍 📖 From b75c7c1041aa56a837a35b6c41b04a5d9680a6e4 Mon Sep 17 00:00:00 2001 From: Allagadda Sai Upendranath Date: Sat, 14 Oct 2023 16:45:12 +0530 Subject: [PATCH 10/26] docs: Update README.md for Page object design pattern (#2597) Fixes #2250 --- page-object/README.md | 63 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/page-object/README.md b/page-object/README.md index 87046a85d917..93777ad2e032 100644 --- a/page-object/README.md +++ b/page-object/README.md @@ -6,13 +6,69 @@ tag: - Decoupling --- +# Page Object Pattern in Java + +## Real World Example + +Consider a web automation scenario where you need to interact with a web page using a test framework like Selenium. The Page Object pattern can be applied to model each web page as a Java class. Each class encapsulates the structure and behavior of the corresponding web page, making it easier to manage and update the automation code. + ## Intent Page Object encapsulates the UI, hiding the underlying UI widgetry of an application (commonly a web application) and providing an application-specific API to allow the manipulation of UI components required for tests. In doing so, it allows the test class itself to focus on the test logic instead. -## Class diagram -![alt text](./etc/page-object.png "Page Object") +## In Plain Words + +The Page Object pattern in Java is a design pattern used in test automation to represent web pages as Java classes. Each class corresponds to a specific web page and contains methods to interact with the elements on that page. This pattern enhances code maintainability and readability in automated testing. + +## Wikipedia Says + +While there isn't a specific Wikipedia entry for the Page Object pattern, it is widely used in software testing, particularly in the context of UI automation. The Page Object pattern helps abstract the details of a web page, providing a cleaner and more maintainable way to interact with web elements in automated tests. + +## Programmatic Example + +Let's create a simple programmatic example of the Page Object pattern for a login page using Selenium in Java: + +```java +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +public class LoginPage { + private final WebDriver driver; + // Web elements on the login page + private final By usernameInput = By.id("username"); + private final By passwordInput = By.id("password"); + private final By loginButton = By.id("login-button"); + + public LoginPage(WebDriver driver) { + this.driver = driver; + } + + // Methods to interact with the login page + + public void enterUsername(String username) { + WebElement usernameElement = driver.findElement(usernameInput); + usernameElement.sendKeys(username); + } + + public void enterPassword(String password) { + WebElement passwordElement = driver.findElement(passwordInput); + passwordElement.sendKeys(password); + } + + public void clickLoginButton() { + WebElement loginButtonElement = driver.findElement(loginButton); + loginButtonElement.click(); + } + + // Other methods specific to the login page if needed +} +``` + +In this example, the `LoginPage` class represents the login page of a web application. It encapsulates the web elements on the page and provides methods to interact with those elements. The actual Selenium WebDriver instance is passed to the constructor, allowing the methods to perform actions on the web page. + +This Page Object can be used in test scripts to interact with the login page without exposing the details of the page structure in the test code, promoting maintainability and reusability. ## Applicability @@ -21,6 +77,9 @@ Use the Page Object pattern when * You are writing automated tests for your web application and you want to separate the UI manipulation required for the tests from the actual test logic. * Make your tests less brittle, and more readable and robust +## Another example with Class diagram +![alt text](./etc/page-object.png "Page Object") + ## Credits * [Martin Fowler - PageObject](http://martinfowler.com/bliki/PageObject.html) From 198c938747a973efc5a7cacb08442c2348be93cb Mon Sep 17 00:00:00 2001 From: Appari Satya Barghav <36763910+satyabarghav@users.noreply.github.com> Date: Sat, 14 Oct 2023 16:53:18 +0530 Subject: [PATCH 11/26] docs: Added another Tutorial Link in Readme (#2608) * Added another link in Readme and updated year in xml * Added Tutorial links to the Readme file --- adapter/README.md | 2 ++ adapter/pom.xml | 2 +- facade/README.md | 9 +++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/adapter/README.md b/adapter/README.md index 27d440438d61..553471816785 100644 --- a/adapter/README.md +++ b/adapter/README.md @@ -107,6 +107,8 @@ Use the Adapter pattern when * [Dzone](https://dzone.com/articles/adapter-design-pattern-in-java) * [Refactoring Guru](https://refactoring.guru/design-patterns/adapter/java/example) * [Baeldung](https://www.baeldung.com/java-adapter-pattern) +* [GeeksforGeeks](https://www.geeksforgeeks.org/adapter-pattern/) + ## Consequences Class and object adapters have different trade-offs. A class adapter diff --git a/adapter/pom.xml b/adapter/pom.xml index d54cbd048708..9307c255d09f 100644 --- a/adapter/pom.xml +++ b/adapter/pom.xml @@ -4,7 +4,7 @@ This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). The MIT License - Copyright © 2014-2022 Ilkka Seppälä + Copyright © 2014-2023 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 diff --git a/facade/README.md b/facade/README.md index 4090f89b8fc5..4efa8f7b76c7 100644 --- a/facade/README.md +++ b/facade/README.md @@ -212,6 +212,15 @@ subsystem independence and portability. If subsystems are dependent, then you can simplify the dependencies between them by making them communicate with each other solely through their facades. +## Tutorials + +*[DigitalOcean](https://www.digitalocean.com/community/tutorials/facade-design-pattern-in-java) +* [Refactoring Guru](https://refactoring.guru/design-patterns/facade) +* [GeekforGeeks](https://www.geeksforgeeks.org/facade-design-pattern-introduction/) +* [Tutorialspoint](https://www.tutorialspoint.com/design_pattern/facade_pattern.htm) + + + ## Credits * [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59) From be0d5e5953de5f7eb6b94aa44a647d9f1b9c274a Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 14 Oct 2023 14:24:43 +0300 Subject: [PATCH 12/26] docs: add satyabarghav as a contributor for doc (#2651) * 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 87fe385d7535..34b407a8cf04 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2661,6 +2661,15 @@ "translation", "doc" ] + }, + { + "login": "satyabarghav", + "name": "Appari Satya Barghav", + "avatar_url": "https://avatars.githubusercontent.com/u/36763910?v=4", + "profile": "https://github.com/satyabarghav", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 08d7edc48364..377729b968dd 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-292-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-293-orange.svg?style=flat-square)](#contributors-)
@@ -450,6 +450,7 @@ This project is licensed under the terms of the MIT license. Antonio Addeo
Antonio Addeo

📖 💻 Allagadda Sai Upendranath
Allagadda Sai Upendranath

📖 Matheus Braga
Matheus Braga

🌍 📖 + Appari Satya Barghav
Appari Satya Barghav

📖 From f79782bea95d976d821929ddb07c8d46df456f86 Mon Sep 17 00:00:00 2001 From: Marcel Ribeiro-Dantas Date: Sat, 14 Oct 2023 12:59:21 -0300 Subject: [PATCH 13/26] fix: Fix minor typos (#2619) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Ribeiro-Dantas Co-authored-by: Ilkka Seppälä --- README.md | 2 +- .../information/microservice/InformationController.java | 2 +- .../com/iluwatar/caching/database/DbManagerFactory.java | 2 +- .../src/main/java/com/iluwatar/circuitbreaker/App.java | 2 +- .../circuitbreaker/DefaultCircuitBreakerTest.java | 2 +- commander/README.md | 2 +- currying/README.md | 2 +- .../java/com/iluwatar/datamapper/DataMapperException.java | 2 +- .../src/main/java/com/iluwatar/embedded/value/App.java | 4 ++-- .../src/main/java/com/iluwatar/event/queue/Audio.java | 2 +- fanout-fanin/README.md | 2 +- .../src/main/java/com/iluwatar/fanout/fanin/Consumer.java | 2 +- .../src/main/java/com/iluwatar/featuretoggle/App.java | 4 ++-- .../propertiesversion/PropertiesFeatureToggleVersion.java | 2 +- .../pattern/tieredversion/TieredFeatureToggleVersion.java | 2 +- .../iluwatar/leaderelection/AbstractMessageManager.java | 2 +- .../src/main/java/com/iluwatar/pageobject/App.java | 2 +- .../main/java/com/iluwatar/pageobject/AlbumListPage.java | 4 ++-- .../src/main/java/com/iluwatar/pageobject/AlbumPage.java | 6 +++--- .../src/main/java/com/iluwatar/pageobject/LoginPage.java | 4 ++-- .../src/main/java/com/iluwatar/partialresponse/Video.java | 2 +- .../main/java/com/iluwatar/serializedentity/Country.java | 2 +- .../java/com/iluwatar/servicetoworker/GiantViewTest.java | 2 +- subclass-sandbox/README.md | 8 ++++---- subclass-sandbox/etc/subclass-sandbox.urm.puml | 2 +- .../java/com/iluwatar/subclasssandbox/Superpower.java | 6 +++--- .../java/com/iluwatar/subclasssandbox/GroundDiveTest.java | 4 ++-- .../java/com/iluwatar/subclasssandbox/SkyLaunchTest.java | 4 ++-- typeobjectpattern/README.md | 1 + .../src/main/java/com/iluwatar/updatemethod/World.java | 2 +- 30 files changed, 43 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 377729b968dd..181a983c7511 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - diff --git a/aggregator-microservices/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationController.java b/aggregator-microservices/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationController.java index 7a1706cac585..88d11e5f4703 100644 --- a/aggregator-microservices/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationController.java +++ b/aggregator-microservices/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationController.java @@ -34,7 +34,7 @@ public class InformationController { /** - * Endpoint to retrieve a product's informations. + * Endpoint to retrieve a product's information. * * @return product inventory. */ diff --git a/caching/src/main/java/com/iluwatar/caching/database/DbManagerFactory.java b/caching/src/main/java/com/iluwatar/caching/database/DbManagerFactory.java index 85c2baead744..ee7a4a04b936 100644 --- a/caching/src/main/java/com/iluwatar/caching/database/DbManagerFactory.java +++ b/caching/src/main/java/com/iluwatar/caching/database/DbManagerFactory.java @@ -25,7 +25,7 @@ package com.iluwatar.caching.database; /** - * Creates the database connection accroding the input parameter. + * Creates the database connection according the input parameter. */ public final class DbManagerFactory { /** diff --git a/circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/App.java b/circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/App.java index dca32740668a..6db5ad93604d 100644 --- a/circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/App.java +++ b/circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/App.java @@ -29,7 +29,7 @@ /** *

* The intention of the Circuit Builder pattern is to handle remote failures robustly, which is to - * mean that if a service is dependant on n number of other services, and m of them fail, we should + * mean that if a service is dependent on n number of other services, and m of them fail, we should * be able to recover from that failure by ensuring that the user can still use the services that * are actually functional, and resources are not tied up by uselessly by the services which are not * working. However, we should also be able to detect when any of the m failing services become diff --git a/circuit-breaker/src/test/java/com/iluwatar/circuitbreaker/DefaultCircuitBreakerTest.java b/circuit-breaker/src/test/java/com/iluwatar/circuitbreaker/DefaultCircuitBreakerTest.java index 817a1e7d0bcf..465371a3aad3 100644 --- a/circuit-breaker/src/test/java/com/iluwatar/circuitbreaker/DefaultCircuitBreakerTest.java +++ b/circuit-breaker/src/test/java/com/iluwatar/circuitbreaker/DefaultCircuitBreakerTest.java @@ -74,7 +74,7 @@ public String call() throws RemoteServiceException { } }; var circuitBreaker = new DefaultCircuitBreaker(mockService, 1, 1, 100); - //Call with the paramater start_time set to huge amount of time in past so that service + //Call with the parameter start_time set to huge amount of time in past so that service //replies with "Ok". Also, state is CLOSED in start var serviceStartTime = System.nanoTime() - 60 * 1000 * 1000 * 1000; var response = circuitBreaker.attemptRequest(); diff --git a/commander/README.md b/commander/README.md index 334bc4463d09..472370f4bbe1 100644 --- a/commander/README.md +++ b/commander/README.md @@ -18,7 +18,7 @@ This pattern can be used when we need to make commits into 2 (or more) databases ## Explanation Handling distributed transactions can be tricky, but if we choose to not handle it carefully, there could be unwanted consequences. Say, we have an e-commerce website which has a Payment microservice and a Shipping microservice. If the shipping is available currently but payment service is not up, or vice versa, how would we deal with it after having already received the order from the user? -We need a mechanism in place which can handle these kinds of situations. We have to direct the order to either one of the services (in this example, shipping) and then add the order into the database of the other service (in this example, payment), since two databses cannot be updated atomically. If currently unable to do it, there should be a queue where this request can be queued, and there has to be a mechanism which allows for a failure in the queueing as well. All this needs to be done by constant retries while ensuring idempotence (even if the request is made several times, the change should only be applied once) by a commander class, to reach a state of eventual consistency. +We need a mechanism in place which can handle these kinds of situations. We have to direct the order to either one of the services (in this example, shipping) and then add the order into the database of the other service (in this example, payment), since two databases cannot be updated atomically. If currently unable to do it, there should be a queue where this request can be queued, and there has to be a mechanism which allows for a failure in the queueing as well. All this needs to be done by constant retries while ensuring idempotence (even if the request is made several times, the change should only be applied once) by a commander class, to reach a state of eventual consistency. ## Credits diff --git a/currying/README.md b/currying/README.md index 044c5df03d1a..9f32c9066e06 100644 --- a/currying/README.md +++ b/currying/README.md @@ -183,7 +183,7 @@ Cons * As shown in the programmatic example above, curried functions with several parameters have a cumbersome type signature (in Java). ## Related patterns -* [Builder patter](https://java-design-patterns.com/patterns/builder/) +* [Builder pattern](https://java-design-patterns.com/patterns/builder/) ## Credits * [Currying in Java](https://www.baeldung.com/java-currying) diff --git a/data-mapper/src/main/java/com/iluwatar/datamapper/DataMapperException.java b/data-mapper/src/main/java/com/iluwatar/datamapper/DataMapperException.java index 0d96a9b3cb4e..3e5419286f70 100644 --- a/data-mapper/src/main/java/com/iluwatar/datamapper/DataMapperException.java +++ b/data-mapper/src/main/java/com/iluwatar/datamapper/DataMapperException.java @@ -25,7 +25,7 @@ package com.iluwatar.datamapper; /** - * Using Runtime Exception for avoiding dependancy on implementation exceptions. This helps in + * Using Runtime Exception for avoiding dependency on implementation exceptions. This helps in * decoupling. * * @author amit.dixit diff --git a/embedded-value/src/main/java/com/iluwatar/embedded/value/App.java b/embedded-value/src/main/java/com/iluwatar/embedded/value/App.java index 3a51629601fd..37ec26179c5c 100644 --- a/embedded-value/src/main/java/com/iluwatar/embedded/value/App.java +++ b/embedded-value/src/main/java/com/iluwatar/embedded/value/App.java @@ -62,7 +62,7 @@ public static void main(String[] args) throws Exception { // Create table for orders - Orders(id, name, orderedBy, city, state, pincode). // We can see that table is different from the Order object we have. - // We're mapping ShippingAddress into city, state, pincode colummns of the database and not creating a separate table. + // We're mapping ShippingAddress into city, state, pincode columns of the database and not creating a separate table. if (dataSource.createSchema()) { LOGGER.info("TABLE CREATED"); LOGGER.info("Table \"Orders\" schema:\n" + dataSource.getSchema()); @@ -95,7 +95,7 @@ public static void main(String[] args) throws Exception { dataSource.removeOrder(1); LOGGER.info("\nOrders Query: {}", dataSource.queryOrders().collect(Collectors.toList()) + "\n"); - //After successfull demonstration of the pattern, drop the table + //After successful demonstration of the pattern, drop the table if (dataSource.deleteSchema()) { LOGGER.info("TABLE DROPPED"); } else { diff --git a/event-queue/src/main/java/com/iluwatar/event/queue/Audio.java b/event-queue/src/main/java/com/iluwatar/event/queue/Audio.java index f668b61c7055..242e6fbddd51 100644 --- a/event-queue/src/main/java/com/iluwatar/event/queue/Audio.java +++ b/event-queue/src/main/java/com/iluwatar/event/queue/Audio.java @@ -144,7 +144,7 @@ private void update() { clip.open(audioStream); clip.start(); } catch (LineUnavailableException e) { - LOGGER.trace("Error occoured while loading the audio: The line is unavailable", e); + LOGGER.trace("Error occurred while loading the audio: The line is unavailable", e); } catch (IOException e) { LOGGER.trace("Input/Output error while loading the audio", e); } catch (IllegalArgumentException e) { diff --git a/fanout-fanin/README.md b/fanout-fanin/README.md index 9f48160f9483..5d519528c6fb 100644 --- a/fanout-fanin/README.md +++ b/fanout-fanin/README.md @@ -18,7 +18,7 @@ service has received the requests. Now the caller will not wait or expect the re Meanwhile, the pattern service will invoke the requests that have come. The requests might complete at different time. These requests will be processed in different instances of the same function in different machines or services. As the -requests get completed, a callback service everytime is called that transforms the result into a common single object format +requests get completed, a callback service every time is called that transforms the result into a common single object format that gets pushed to a consumer. The caller will be at the other end of the consumer receiving the result. **Programmatic Example** diff --git a/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/Consumer.java b/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/Consumer.java index acb1f2a054da..90b7c63855e3 100644 --- a/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/Consumer.java +++ b/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/Consumer.java @@ -30,7 +30,7 @@ /** - * Consumer or callback class that will be called everytime a request is complete This will + * Consumer or callback class that will be called every time a request is complete This will * aggregate individual result to form a final result. */ @Getter diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java index 1f5359e195ae..421f86e4c2eb 100644 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java @@ -39,8 +39,8 @@ * version of the feature toggle, where the enhanced version of the welcome message which is * personalised is turned either on or off at instance creation. This method is not as dynamic as * the {@link User} driven version where the feature of the personalised welcome message is - * dependant on the {@link UserGroup} the {@link User} is in. So if the user is a memeber of the - * {@link UserGroup#isPaid(User)} then they get an ehanced version of the welcome message. + * dependent on the {@link UserGroup} the {@link User} is in. So if the user is a member of the + * {@link UserGroup#isPaid(User)} then they get an enhanced version of the welcome message. * *

Note that this pattern can easily introduce code complexity, and if not kept in check can * result in redundant unmaintained code within the codebase. diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java index e70a581a6c5e..ce7886a10039 100644 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java @@ -30,7 +30,7 @@ import lombok.Getter; /** - * This example of the Feature Toogle pattern is less dynamic version than {@link + * This example of the Feature Toggle pattern is less dynamic version than {@link * com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} where the feature is * turned on or off at the time of creation of the service. This example uses simple Java {@link * Properties} however it could as easily be done with an external configuration file loaded by diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java index f846f990c9d9..74eb44340940 100644 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java @@ -29,7 +29,7 @@ import com.iluwatar.featuretoggle.user.UserGroup; /** - * This example of the Feature Toogle pattern shows how it could be implemented based on a {@link + * This example of the Feature Toggle pattern shows how it could be implemented based on a {@link * User}. Therefore showing its use within a tiered application where the paying users get access to * different content or better versions of features. So in this instance a {@link User} is passed in * and if they are found to be on the {@link UserGroup#isPaid(User)} they are welcomed with a diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/AbstractMessageManager.java b/leader-election/src/main/java/com/iluwatar/leaderelection/AbstractMessageManager.java index eab9787d80a2..82f89f89c8fa 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/AbstractMessageManager.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/AbstractMessageManager.java @@ -37,7 +37,7 @@ public abstract class AbstractMessageManager implements MessageManager { protected Map instanceMap; /** - * Construtor of AbstractMessageManager. + * Constructor of AbstractMessageManager. */ public AbstractMessageManager(Map instanceMap) { this.instanceMap = instanceMap; diff --git a/page-object/sample-application/src/main/java/com/iluwatar/pageobject/App.java b/page-object/sample-application/src/main/java/com/iluwatar/pageobject/App.java index ef18ea41839f..0913af68e538 100644 --- a/page-object/sample-application/src/main/java/com/iluwatar/pageobject/App.java +++ b/page-object/sample-application/src/main/java/com/iluwatar/pageobject/App.java @@ -83,7 +83,7 @@ public static void main(String[] args) { } } catch (IOException ex) { - LOGGER.error("An error occured.", ex); + LOGGER.error("An error occurred.", ex); } } diff --git a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumListPage.java b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumListPage.java index 7ea05d6c8c09..83917be917aa 100644 --- a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumListPage.java +++ b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumListPage.java @@ -59,7 +59,7 @@ public AlbumListPage navigateToPage() { try { page = this.webClient.getPage(PAGE_URL); } catch (IOException e) { - LOGGER.error("An error occured on navigateToPage.", e); + LOGGER.error("An error occurred on navigateToPage.", e); } return this; } @@ -87,7 +87,7 @@ public AlbumPage selectAlbum(String albumTitle) { ((HtmlAnchor) anchor).click(); return new AlbumPage(webClient); } catch (IOException e) { - LOGGER.error("An error occured on selectAlbum", e); + LOGGER.error("An error occurred on selectAlbum", e); } } } diff --git a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumPage.java b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumPage.java index 52af795996a5..625293a7a2cc 100644 --- a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumPage.java +++ b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumPage.java @@ -61,7 +61,7 @@ public AlbumPage navigateToPage() { try { page = this.webClient.getPage(PAGE_URL); } catch (IOException e) { - LOGGER.error("An error occured on navigateToPage.", e); + LOGGER.error("An error occurred on navigateToPage.", e); } return this; } @@ -151,7 +151,7 @@ public AlbumListPage cancelChanges() { try { cancelButton.click(); } catch (IOException e) { - LOGGER.error("An error occured on cancelChanges.", e); + LOGGER.error("An error occurred on cancelChanges.", e); } return new AlbumListPage(webClient); } @@ -167,7 +167,7 @@ public AlbumPage saveChanges() { try { saveButton.click(); } catch (IOException e) { - LOGGER.error("An error occured on saveChanges.", e); + LOGGER.error("An error occurred on saveChanges.", e); } return this; } diff --git a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/LoginPage.java b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/LoginPage.java index d2c963031298..f87b58e76867 100644 --- a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/LoginPage.java +++ b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/LoginPage.java @@ -60,7 +60,7 @@ public LoginPage navigateToPage() { try { page = this.webClient.getPage(PAGE_URL); } catch (IOException e) { - LOGGER.error("An error occured on navigateToPage.", e); + LOGGER.error("An error occurred on navigateToPage.", e); } return this; } @@ -111,7 +111,7 @@ public AlbumListPage login() { try { loginButton.click(); } catch (IOException e) { - LOGGER.error("An error occured on login.", e); + LOGGER.error("An error occurred on login.", e); } return new AlbumListPage(webClient); } diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java b/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java index 5c71f9bb37d3..28604ca0acf9 100644 --- a/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java +++ b/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java @@ -33,7 +33,7 @@ public record Video(Integer id, String title, Integer length, String description /** * ToString. * - * @return json representaion of video + * @return json representation of video */ @Override public String toString() { diff --git a/serialized-entity/src/main/java/com/iluwatar/serializedentity/Country.java b/serialized-entity/src/main/java/com/iluwatar/serializedentity/Country.java index e1eb3c22a868..6ef08e83b8d6 100644 --- a/serialized-entity/src/main/java/com/iluwatar/serializedentity/Country.java +++ b/serialized-entity/src/main/java/com/iluwatar/serializedentity/Country.java @@ -31,7 +31,7 @@ import lombok.ToString; /** - * A Country POJO taht represents the data that will serialize and store in database. + * A Country POJO that represents the data that will serialize and store in database. */ @Getter @Setter diff --git a/service-to-worker/src/test/java/com/iluwatar/servicetoworker/GiantViewTest.java b/service-to-worker/src/test/java/com/iluwatar/servicetoworker/GiantViewTest.java index 579f991a93d1..8f5f3bb359e9 100644 --- a/service-to-worker/src/test/java/com/iluwatar/servicetoworker/GiantViewTest.java +++ b/service-to-worker/src/test/java/com/iluwatar/servicetoworker/GiantViewTest.java @@ -37,7 +37,7 @@ class GiantViewTest { /** - * Test dispaly giant. + * Test display giant. */ @Test void testDispalyGiant() { diff --git a/subclass-sandbox/README.md b/subclass-sandbox/README.md index d76c149eedc4..7a4587e3d4d5 100644 --- a/subclass-sandbox/README.md +++ b/subclass-sandbox/README.md @@ -32,8 +32,8 @@ public abstract class Superpower { logger.info("Move to ( " + x + ", " + y + ", " + z + " )"); } - protected void playSound(String soundName, int volumn) { - logger.info("Play " + soundName + " with volumn " + volumn); + protected void playSound(String soundName, int volume) { + logger.info("Play " + soundName + " with volume " + volume); } protected void spawnParticles(String particleType, int count) { @@ -88,11 +88,11 @@ Program output: ``` // Use superpower: sky launch // Move to ( 0.0, 0.0, 20.0 ) -// Play SKYLAUNCH_SOUND with volumn 1 +// Play SKYLAUNCH_SOUND with volume 1 // Spawn 100 particle with type SKYLAUNCH_PARTICLE // Use superpower: ground dive // Move to ( 0.0, 0.0, -20.0 ) -// Play GROUNDDIVE_SOUND with volumn 5 +// Play GROUNDDIVE_SOUND with volume 5 // Spawn 20 particle with type GROUNDDIVE_PARTICLE ``` ## Class diagram diff --git a/subclass-sandbox/etc/subclass-sandbox.urm.puml b/subclass-sandbox/etc/subclass-sandbox.urm.puml index a1f863b697c9..9c9fda5994a0 100644 --- a/subclass-sandbox/etc/subclass-sandbox.urm.puml +++ b/subclass-sandbox/etc/subclass-sandbox.urm.puml @@ -18,7 +18,7 @@ package com.iluwatar.subclasssandbox { + Superpower() # activate() {abstract} # move(x : double, y : double, z : double) - # playSound(soundName : String, volumn : int) + # playSound(soundName : String, volume : int) # spawnParticles(particleType : String, count : int) } } diff --git a/subclass-sandbox/src/main/java/com/iluwatar/subclasssandbox/Superpower.java b/subclass-sandbox/src/main/java/com/iluwatar/subclasssandbox/Superpower.java index d3472323e225..4e520f39754e 100644 --- a/subclass-sandbox/src/main/java/com/iluwatar/subclasssandbox/Superpower.java +++ b/subclass-sandbox/src/main/java/com/iluwatar/subclasssandbox/Superpower.java @@ -53,10 +53,10 @@ protected void move(double x, double y, double z) { /** * Play sound effect for the superpower. * @param soundName Sound name. - * @param volumn Value of volumn. + * @param volume Value of volume. */ - protected void playSound(String soundName, int volumn) { - logger.info("Play " + soundName + " with volumn " + volumn); + protected void playSound(String soundName, int volume) { + logger.info("Play " + soundName + " with volume " + volume); } /** diff --git a/subclass-sandbox/src/test/java/com/iluwatar/subclasssandbox/GroundDiveTest.java b/subclass-sandbox/src/test/java/com/iluwatar/subclasssandbox/GroundDiveTest.java index 05104fa29f86..03c6b2e5c8ba 100644 --- a/subclass-sandbox/src/test/java/com/iluwatar/subclasssandbox/GroundDiveTest.java +++ b/subclass-sandbox/src/test/java/com/iluwatar/subclasssandbox/GroundDiveTest.java @@ -48,7 +48,7 @@ void testMove() throws Exception { void testPlaySound() throws Exception { var groundDive = new GroundDive(); var outputLog = getLogContent(() -> groundDive.playSound("SOUND_NAME", 1)); - var expectedLog = "Play SOUND_NAME with volumn 1"; + var expectedLog = "Play SOUND_NAME with volume 1"; assertEquals(outputLog, expectedLog); } @@ -70,7 +70,7 @@ void testActivate() throws Exception { final var log1 = logs[0].split("-")[1].trim() + " -" + logs[0].split("-")[2].trim(); final var expectedLog1 = "Move to ( 0.0, 0.0, -20.0 )"; final var log2 = getLogContent(logs[1]); - final var expectedLog2 = "Play GROUNDDIVE_SOUND with volumn 5"; + final var expectedLog2 = "Play GROUNDDIVE_SOUND with volume 5"; final var log3 = getLogContent(logs[2]); final var expectedLog3 = "Spawn 20 particle with type GROUNDDIVE_PARTICLE"; assertEquals(logs.length, expectedSize); diff --git a/subclass-sandbox/src/test/java/com/iluwatar/subclasssandbox/SkyLaunchTest.java b/subclass-sandbox/src/test/java/com/iluwatar/subclasssandbox/SkyLaunchTest.java index 0a199c20e9b5..87cee4f3c697 100644 --- a/subclass-sandbox/src/test/java/com/iluwatar/subclasssandbox/SkyLaunchTest.java +++ b/subclass-sandbox/src/test/java/com/iluwatar/subclasssandbox/SkyLaunchTest.java @@ -47,7 +47,7 @@ void testMove() throws Exception { void testPlaySound() throws Exception { var skyLaunch = new SkyLaunch(); var outputLog = getLogContent(() -> skyLaunch.playSound("SOUND_NAME", 1)); - var expectedLog = "Play SOUND_NAME with volumn 1"; + var expectedLog = "Play SOUND_NAME with volume 1"; assertEquals(outputLog, expectedLog); } @@ -69,7 +69,7 @@ void testActivate() throws Exception { final var log1 = getLogContent(logs[0]); final var expectedLog1 = "Move to ( 0.0, 0.0, 20.0 )"; final var log2 = getLogContent(logs[1]); - final var expectedLog2 = "Play SKYLAUNCH_SOUND with volumn 1"; + final var expectedLog2 = "Play SKYLAUNCH_SOUND with volume 1"; final var log3 = getLogContent(logs[2]); final var expectedLog3 = "Spawn 100 particle with type SKYLAUNCH_PARTICLE"; assertEquals(logs.length, expectedSize); diff --git a/typeobjectpattern/README.md b/typeobjectpattern/README.md index 742792a8f423..b8d984f4d3a6 100644 --- a/typeobjectpattern/README.md +++ b/typeobjectpattern/README.md @@ -19,6 +19,7 @@ As explained in the book Game Programming Patterns by Robert Nystrom, type objec > Allowing flexible creation of new “classes” by creating a single class, each instance of which represents a different type of object ## Real World Example + Let's consider a real-world example. Say, we are working on a game which has a hero and many monsters which are going to attack the hero. These monsters have certain attributes like attack, points etc. and come in different 'breeds' like zombie or ogres. The obvious answer is to have a base Monster class which has some fields and methods, which may be overriden by subclasses like the Zombie or Ogre class. But as we continue to build the game, there may be more and more breeds of monsters added and certain attributes may need to be changed in the existing monsters too. The OOP solution of inheriting from the base class would not be an efficient method in this case. Using the type-object pattern, instead of creating many classes inheriting from a base class, we have 1 class with a field which represents the 'type' of object. This makes the code cleaner and object instantiation also becomes as easy as parsing a json file with the object properties. diff --git a/update-method/src/main/java/com/iluwatar/updatemethod/World.java b/update-method/src/main/java/com/iluwatar/updatemethod/World.java index f2da8b9f89b1..5335b23f12f0 100644 --- a/update-method/src/main/java/com/iluwatar/updatemethod/World.java +++ b/update-method/src/main/java/com/iluwatar/updatemethod/World.java @@ -74,7 +74,7 @@ private void processInput() { } /** - * Update internal status. The update method pattern invoke udpate method for + * Update internal status. The update method pattern invoke update method for * each entity in the game. */ private void update() { From 4c9b80b137e616ed2f78e307657d7142d5138603 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 14 Oct 2023 19:00:14 +0300 Subject: [PATCH 14/26] docs: add mribeirodantas as a contributor for doc (#2653) * 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 34b407a8cf04..fe972a4578de 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2670,6 +2670,15 @@ "contributions": [ "doc" ] + }, + { + "login": "mribeirodantas", + "name": "Marcel Ribeiro-Dantas", + "avatar_url": "https://avatars.githubusercontent.com/u/1023197?v=4", + "profile": "http://mribeirodantas.me", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 181a983c7511..496196a7bce7 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-293-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-294-orange.svg?style=flat-square)](#contributors-)
@@ -451,6 +451,7 @@ This project is licensed under the terms of the MIT license. Allagadda Sai Upendranath
Allagadda Sai Upendranath

📖 Matheus Braga
Matheus Braga

🌍 📖 Appari Satya Barghav
Appari Satya Barghav

📖 + Marcel Ribeiro-Dantas
Marcel Ribeiro-Dantas

📖 From a2d89939876c9290d77d57afec6e59469ef7ad4f Mon Sep 17 00:00:00 2001 From: Muhammad Hanif Amrullah <74542852+hamexhanif@users.noreply.github.com> Date: Sun, 15 Oct 2023 15:19:18 +0200 Subject: [PATCH 15/26] translation: added for Indonesian decorator pattern #2280 (#2620) --- localization/id/decorator/README.md | 169 ++++++++++++++++++ .../id/decorator/etc/decorator.urm.png | Bin 0 -> 23530 bytes 2 files changed, 169 insertions(+) create mode 100644 localization/id/decorator/README.md create mode 100644 localization/id/decorator/etc/decorator.urm.png diff --git a/localization/id/decorator/README.md b/localization/id/decorator/README.md new file mode 100644 index 000000000000..1fe3d89241ba --- /dev/null +++ b/localization/id/decorator/README.md @@ -0,0 +1,169 @@ +--- +title: Decorator +category: Structural +language: id +tag: + - Gang of Four + - Extensibility +--- + +## Juga dikenal sebagai + +Pembungkus + +## Tujuan + +Menyematkan tanggung jawab tambahan ke suatu objek secara dinamis. Dekorator memberikan alternatif yang fleksibel terhadap subkelas untuk memperluas fungsionalitas. + +## Penjelasan + +Contoh dunia nyata + +> Ada troll pemarah yang tinggal di perbukitan terdekat. Biasanya ia pergi dengan tangan kosong, tetapi terkadang ia +> punya senjata. Untuk mempersenjatai troll, Anda tidak perlu membuat troll baru, melainkan mendekorasinya +> secara dinamis dengan senjata yang sesuai. + +Dengan kata sederhana + +> Pola dekorator memungkinkan Anda mengubah perilaku objek secara dinamis saat run time dengan membungkus +> mereka dalam objek kelas dekorator. + +Wikipedia(en) mengatakan + +> Dalam pemrograman berorientasi objek, pola dekorator adalah pola desain yang memungkinkan perilaku +> ditambahkan ke objek individual, baik secara statis maupun dinamis, tanpa memengaruhi perilaku +> objek lain dari kelas yang sama. Pola dekorator sering kali berguna untuk mematuhi Prinsip Tanggung +> Jawab Tunggal, karena memungkinkan fungsionalitas dibagi antara kelas-kelas dengan area perhatian yang +> unik serta Prinsip Terbuka-Tertutup, dengan memungkinkan fungsionalitas suatu kelas diperluas tanpa diubah. + +**Contoh Program** + +Mari kita ambil contoh troll. Pertama-tama kita memiliki `SimpleTroll` yang mengimplementasikan antarmuka +`Troll`: + +```java +public interface Troll { + void attack(); + int getAttackPower(); + void fleeBattle(); +} + +@Slf4j +public class SimpleTroll implements Troll { + + @Override + public void attack() { + LOGGER.info("Troll itu mencoba menangkapmu!"); + } + + @Override + public int getAttackPower() { + return 10; + } + + @Override + public void fleeBattle() { + LOGGER.info("Troll itu menjerit ketakutan dan melarikan diri!"); + } +} +``` + +Kemudian kita ingin menambahkan gada untuk troll tersebut. Kita dapat melakukannya secara dinamis dengan menggunakan dekorator: + +```java +@Slf4j +public class ClubbedTroll implements Troll { + + private final Troll decorated; + + public ClubbedTroll(Troll decorated) { + this.decorated = decorated; + } + + @Override + public void attack() { + decorated.attack(); + LOGGER.info("Troll itu mengayunkan gada ke arahmu!"); + } + + @Override + public int getAttackPower() { + return decorated.getAttackPower() + 10; + } + + @Override + public void fleeBattle() { + decorated.fleeBattle(); + } +} +``` + +Berikut aksi troll tersebut: + +```java +// simple troll +LOGGER.info("Troll biasa mendekat."); +var troll = new SimpleTroll(); +troll.attack(); +troll.fleeBattle(); +LOGGER.info("Kekuatan troll sederhana: {}.\n", troll.getAttackPower()); + +// change the behavior of the simple troll by adding a decorator +LOGGER.info("Troll dengan gada besar mengejutkanmu."); +var clubbedTroll = new ClubbedTroll(troll); +clubbedTroll.attack(); +clubbedTroll.fleeBattle(); +LOGGER.info("Kekuatan troll dengan gada: {}.\n", clubbedTroll.getAttackPower()); +``` + +Output program: + +```java +Troll biasa mendekat. +Troll itu mencoba menangkapmu! +Troll itu menjerit ketakutan dan melarikan diri! +Kekuatan troll sederhana: 10. + +Troll dengan gada besar mengejutkanmu. +Troll itu mencoba menangkapmu! +Troll itu mengayunkan gada ke arahmu! +Troll itu menjerit ketakutan dan melarikan diri! +Kekuatan troll dengan gada: 20. +``` + +## Diagram kelas + +![alt text](./etc/decorator.urm.png "Diagram kelas pola dekorator") + +## Penerapan + +Dekorator digunakan untuk: + +* Tambahkan tanggung jawab ke objek individual secara dinamis dan transparan, tanpa +memengaruhi objek lain. +* Untuk tanggung jawab yang dapat ditarik/dihapus. +* Dimana ekstensi dengan subkelas tidak praktis; Ketika sejumlah besar ekstensi independen +mungkin dilakukan dan akan menghasilkan ledakan subkelas untuk mendukung setiap kombinasi, atau definisi +kelas mungkin tersembunyi dan/atau tidak tersedia untuk subkelas. + +## Tutorial + +* [Tutorial Pola Dekorator](https://www.journaldev.com/1540/decorator-design-pattern-in-java-example) + +## Kegunaan yang diketahui + + * [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) dan [java.io.Writer](http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html) + * [java.util.Collections#synchronizedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedCollection-java.util.Collection-) + * [java.util.Collections#unmodifiableXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableCollection-java.util.Collection-) + * [java.util.Collections#checkedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedCollection-java.util.Collection-java.lang.Class-) + + +## Kredit + +* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59) +* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b) +* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31) +* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b) +* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7) +* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94) diff --git a/localization/id/decorator/etc/decorator.urm.png b/localization/id/decorator/etc/decorator.urm.png new file mode 100644 index 0000000000000000000000000000000000000000..141c0563f0c6c79c0fbeb125278dfbc151ffd6a0 GIT binary patch literal 23530 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 literal 0 HcmV?d00001 From 9e2c8c520eb9a7cdedb63ef0f0d4a880e13866d3 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 16:20:06 +0300 Subject: [PATCH 16/26] docs: add hamexhanif as a contributor for translation (#2657) * 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 | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index fe972a4578de..d2060ca85b49 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2679,6 +2679,15 @@ "contributions": [ "doc" ] + }, + { + "login": "hamexhanif", + "name": "Muhammad Hanif Amrullah", + "avatar_url": "https://avatars.githubusercontent.com/u/74542852?v=4", + "profile": "https://github.com/hamexhanif", + "contributions": [ + "translation" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 496196a7bce7..985e4bd9e93f 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-294-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-295-orange.svg?style=flat-square)](#contributors-)
@@ -453,6 +453,9 @@ This project is licensed under the terms of the MIT license. Appari Satya Barghav
Appari Satya Barghav

📖 Marcel Ribeiro-Dantas
Marcel Ribeiro-Dantas

📖 + + Muhammad Hanif Amrullah
Muhammad Hanif Amrullah

🌍 + From f9ae5961e6cc3dbb3c3cee16d56fb1f39c8e5b0f Mon Sep 17 00:00:00 2001 From: JackH408 <141727294+JackH408@users.noreply.github.com> Date: Mon, 16 Oct 2023 00:22:15 +1100 Subject: [PATCH 17/26] docs: Explanation for Feature Toggle #2230 Finished (#2622) * Added documentation for Feature Toggle design pattern * Explanation for Feature Toggle Issue #2230 finished, added intent, explanation, programmatic example, applicability and consequences --- feature-toggle/README.md | 64 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/feature-toggle/README.md b/feature-toggle/README.md index 915a255690da..982108bc7440 100644 --- a/feature-toggle/README.md +++ b/feature-toggle/README.md @@ -10,10 +10,53 @@ tag: Feature Flag ## Intent -Used to switch code execution paths based on properties or groupings. Allowing new features to be released, tested -and rolled out. Allowing switching back to the older feature quickly if needed. It should be noted that this pattern, -can easily introduce code complexity. There is also cause for concern that the old feature that the toggle is eventually -going to phase out is never removed, causing redundant code smells and increased maintainability. +A technique used in software development to control and manage the rollout of specific features or functionality in a +program without changing the code. It can act as an on/off switch for features depending on the status or properties of +other values in the program. This is similar to A/B testing, where features are rolled out based on properties such as +location or device. Implementing this design pattern can increase code complexity, and it is important to remember to +remove redundant code if this design pattern is being used to phase out a system or feature. + +## Explanation +Real-world Example +> This design pattern works really well in any sort of development, in particular mobile development. Say you want to +> introduce a feature such as dark mode, but you want to ensure that the feature works correctly and don't want to roll +> out the feature to everyone immediately. You write in the code, and have it switched off as default. From here, it is +> easy to turn on the code for specific users based on selection criteria, or randomly. This will also allow the feature +> to be turned off easily without any drastic changes to the code, or any need for redeployment or updates. + +In plain words +> Feature Toggle is a way to introduce new features gradually instead of deployment all at once. + +Wikipedia says +> A feature toggle in software development provides an alternative to maintaining multiple feature branches in source +> code. A condition within the code enables or disables a feature during runtime. In agile settings the toggle is +> used in production, to switch on the feature on demand, for some or all the users. + +## Programmatic Example +This example shows Java code that allows a feature to show when it is enabled by the developer, and when a user is a +Premium member of the application. This is useful for subscription locked features. +```java +public class FeatureToggleExample { + // Bool for feature enabled or disabled + private static boolean isNewFeatureEnabled = false; + + public static void main(String[] args) { + boolean userIsPremium = true; // Example: Check if the user is a premium user + + // Check if the new feature should be enabled for the user + if (userIsPremium && isNewFeatureEnabled) { + // User is premium and the new feature is enabled + showNewFeature(); + } + } + + private static void showNewFeature() { + // If user is allowed to see locked feature, this is where the code would go + } +} +``` +The code shows how simple it is to implement this design pattern, and the criteria can be further refined or broadened +should the developers choose to do so. ## Class diagram ![alt text](./etc/feature-toggle.png "Feature Toggle") @@ -24,7 +67,20 @@ Use the Feature Toggle pattern when * Giving different features to different users. * Rolling out a new feature incrementally. * Switching between development and production environments. +* Quickly disable problematic features +* External management of feature deployment +* Ability to maintain multiple version releases of a feature +* 'Hidden' deployment, releasing a feature in code for designated testing but not publicly making it available + +## Consequences +Consequences involved with using the Feature Toggle pattern + +* Code complexity is increased +* Testing of multiple states is harder and more time-consuming +* Confusion between friends on why features are missing +* Keeping documentation up to date with all features can be difficult ## Credits * [Martin Fowler 29 October 2010 (2010-10-29).](http://martinfowler.com/bliki/FeatureToggle.html) +* [Feature Toggle - Java Design Patterns](https://java-design-patterns.com/patterns/feature-toggle/) From 845fa9da34ad12430ed84464570ba53a105a7766 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 16:23:06 +0300 Subject: [PATCH 18/26] docs: add JackH408 as a contributor for doc (#2658) * 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 d2060ca85b49..b68cba50ea37 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2688,6 +2688,15 @@ "contributions": [ "translation" ] + }, + { + "login": "JackH408", + "name": "JackH408", + "avatar_url": "https://avatars.githubusercontent.com/u/141727294?v=4", + "profile": "https://github.com/JackH408", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 985e4bd9e93f..4486cdf54015 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-295-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-296-orange.svg?style=flat-square)](#contributors-)
@@ -455,6 +455,7 @@ This project is licensed under the terms of the MIT license. Muhammad Hanif Amrullah
Muhammad Hanif Amrullah

🌍 + JackH408
JackH408

📖 From 31b7df23d216f4cce162815b3580435b83a850f2 Mon Sep 17 00:00:00 2001 From: Tien Nguyen Minh <39063457+tiennm99@users.noreply.github.com> Date: Sun, 15 Oct 2023 20:25:22 +0700 Subject: [PATCH 19/26] translation: Add aggregator microservices pattern translation #2288 (#2582) * [Translate, Vietnamese] (Add) aggregator microservices pattern translation * [Translate, Vietnamese] (Fix) comment suggestions --- .../vi/aggregator-microservices/README.md | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 localization/vi/aggregator-microservices/README.md diff --git a/localization/vi/aggregator-microservices/README.md b/localization/vi/aggregator-microservices/README.md new file mode 100644 index 000000000000..b36a388fc9cb --- /dev/null +++ b/localization/vi/aggregator-microservices/README.md @@ -0,0 +1,102 @@ +--- +title: Microservices Tổng Hợp +category: Architectural +language: vi +tag: +- Cloud distributed +- Decoupling +- Microservices +--- + +## Mục Đích +Người dùng chỉ cần thực hiện một lần gọi duy nhất đến dịch vụ tổng hợp, sau đó dịch vụ tổng hợp sẽ gọi dịch vụ con tương ứng. + +## Giải Thích + +Ví dụ thực tế + +> Trang web thị trường của chúng ta cần thông tin về sản phẩm và tồn kho hiện tại của chúng. Nó thực hiện gọi đến dịch vụ tổng hợp, sau đó dịch vụ tổng hợp gọi dịch vụ thông tin sản phẩm và dịch vụ tồn kho sản phẩm, cuối cùng trả lại thông tin kết hợp. + +## Nói đơn giản hơn + +> Microservices Tổng Hợp thu thập các phần dữ liệu từ các dịch vụ con khác nhau và trả về một tổng hợp để xử lý. + +Theo Stack Overflow + +> Microservices Tổng Hợp gọi nhiều dịch vụ để đạt được chức năng được yêu cầu bởi ứng dụng. + +**Mã nguồn mẫu** + +Hãy bắt đầu từ mô hình dữ liệu. Đây là lớp `Product` của chúng ta. + +```java +public class Product { + private String title; + private int productInventories; + // getters and setters -> + ... +} +``` + +Tiếp theo, chúng ta có thể giới thiệu Microservices `Aggregator` của chúng ta. Nó chứa các khách hàng `ProductInformationClient` và +`ProductInventoryClient` để gọi các dịch vụ con tương ứng. + +```java +@RestController +public class Aggregator { + + @Resource + private ProductInformationClient informationClient; + + @Resource + private ProductInventoryClient inventoryClient; + + @RequestMapping(path = "/product", method = RequestMethod.GET) + public Product getProduct() { + + var product = new Product(); + var productTitle = informationClient.getProductTitle(); + var productInventory = inventoryClient.getProductInventories(); + + //Fallback to error message + product.setTitle(requireNonNullElse(productTitle, "Error: Fetching Product Title Failed")); + + //Fallback to default error inventory + product.setProductInventories(requireNonNullElse(productInventory, -1)); + + return product; + } +} +``` + +Dưới đây là bản thể của việc triển khai dịch vụ thông tin sản phẩm. Dịch vụ tồn kho cũng tương tự như thế, nó chỉ trả về số lượng tồn kho. + +```java +@RestController +public class InformationController { + @RequestMapping(value = "/information", method = RequestMethod.GET) + public String getProductTitle() { + return "The Product Title."; + } +} +``` + +Bây giờ, việc gọi `Aggregator` API REST của chúng ta sẽ trả về thông tin sản phẩm. + +```bash +curl http://localhost:50004/product +{"title":"The Product Title.","productInventories":5} +``` + +## Sơ Đồ Lớp +![alt text](../../../aggregator-microservices/aggregator-service/etc/aggregator-service.png "Aggregator Microservice") + + +## Các Trường Hợp Sử Dụng +Sử dụng mẫu Microservices Tổng Hợp khi bạn cần một API chung cho các dịch vụ Microservices khác nhau, bất kể thiết bị của khách hàng. + +## Người Đóng Góp + +* [Microservice Design Patterns](http://web.archive.org/web/20190705163602/http://blog.arungupta.me/microservice-design-patterns/) +* [Microservices Patterns: With examples in Java](https://www.amazon.com/gp/product/1617294543/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617294543&linkId=8b4e570267bc5fb8b8189917b461dc60) +* [Architectural Patterns: Uncover essential patterns in the most indispensable realm of enterprise architecture](https://www.amazon.com/gp/product/B077T7V8RC/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=B077T7V8RC&linkId=c34d204bfe1b277914b420189f09c1a4) From 021eb03b4ecbda704db3819659fa4137a11b0acc Mon Sep 17 00:00:00 2001 From: Shubham <132815243+versus2004@users.noreply.github.com> Date: Sun, 15 Oct 2023 19:05:54 +0530 Subject: [PATCH 20/26] translation: Hindi translation for module pattern (#2593) Hindi translation for module --- localization/hi/module/README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 localization/hi/module/README.md diff --git a/localization/hi/module/README.md b/localization/hi/module/README.md new file mode 100644 index 000000000000..8d8a78ae4aa3 --- /dev/null +++ b/localization/hi/module/README.md @@ -0,0 +1,27 @@ +--- +title: Module +category: Structural +language: hi +tag: + - Decoupling + - Cloud distributed +--- + +## हेतु + +मॉड्यूल पैटर्न का उपयोग सॉफ़्टवेयर मॉड्यूल की अवधारणा को लागू करने के लिए किया जाता है, जिसे मॉड्यूलर प्रोग्रामिंग द्वारा परिभाषित किया जाता है, एक प्रोग्रामिंग भाषा में जो अवधारणा के लिए अपूर्ण प्रत्यक्ष समर्थन प्रदान करती है। + +## क्लास डायग्राम + + +![alt text](../../../module/etc/module.png "Module class diagram") + +## प्रयोज्यता + +मॉड्यूल पैटर्न को एक क्रिएशनल पैटर्न और एक स्ट्रक्चरल पैटर्न माना जा सकता है। यह अन्य तत्वों के निर्माण और संगठन को प्रबंधित करता है, और उन्हें स्ट्रक्चरल पैटर्न की तरह समूहों में विभाजित करता है। + +इस पैटर्न को लागू करने वाली कोई वस्तु एक नामस्थान के समकक्ष प्रदान कर सकती है, जो एक स्थैतिक वर्ग या स्थैतिक सदस्यों वाले वर्ग के आरंभीकरण और अंतिमकरण प्रक्रिया को क्लीनर, अधिक संक्षिप्त वाक्यविन्यास और अर्थशास्त्र के साथ प्रदान करती है। + +## श्रेय + +* [Module](https://en.wikipedia.org/wiki/Module_pattern) From 3fee2094072d60e09a5549f472708114e36c2ce5 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 16:36:39 +0300 Subject: [PATCH 21/26] docs: add versus2004 as a contributor for translation (#2659) * 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 b68cba50ea37..7b21695d4ede 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2697,6 +2697,15 @@ "contributions": [ "doc" ] + }, + { + "login": "versus2004", + "name": "Shubham", + "avatar_url": "https://avatars.githubusercontent.com/u/132815243?v=4", + "profile": "https://github.com/versus2004", + "contributions": [ + "translation" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 4486cdf54015..c11a3965af9e 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-296-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-297-orange.svg?style=flat-square)](#contributors-)
@@ -456,6 +456,7 @@ This project is licensed under the terms of the MIT license. Muhammad Hanif Amrullah
Muhammad Hanif Amrullah

🌍 JackH408
JackH408

📖 + Shubham
Shubham

🌍 From f9c5e7ef4c9a830baa392e310c572c7d2611e57c Mon Sep 17 00:00:00 2001 From: Nishant Jain <121454072+inishantjain@users.noreply.github.com> Date: Sun, 15 Oct 2023 19:07:28 +0530 Subject: [PATCH 22/26] docs: removed weird link from mvvm (#2618) --- model-view-viewmodel/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/model-view-viewmodel/README.md b/model-view-viewmodel/README.md index 859a14fa6f0a..ab8b20628934 100644 --- a/model-view-viewmodel/README.md +++ b/model-view-viewmodel/README.md @@ -114,7 +114,6 @@ To deploy the example, go to model-view-viewmodel folder and run: ## Tutorials * [Zkoss Demo](https://www.zkoss.org/zkdemo/getting_started/mvvm) -* [Learn MVVM](https://www.learnmvvm.com/) * [Data Binding in Android](https://developer.android.com/codelabs/android-databinding#0) ## Typical Use Case From 479b2e6e00a0b24dd53c1008e55b1e8a41ea0a76 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 16:38:22 +0300 Subject: [PATCH 23/26] docs: add inishantjain as a contributor for doc (#2660) * 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 7b21695d4ede..ea3d134770c1 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2706,6 +2706,15 @@ "contributions": [ "translation" ] + }, + { + "login": "inishantjain", + "name": "Nishant Jain", + "avatar_url": "https://avatars.githubusercontent.com/u/121454072?v=4", + "profile": "https://github.com/inishantjain", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index c11a3965af9e..662a8a57e10c 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-297-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-298-orange.svg?style=flat-square)](#contributors-)
@@ -457,6 +457,7 @@ This project is licensed under the terms of the MIT license. Muhammad Hanif Amrullah
Muhammad Hanif Amrullah

🌍 JackH408
JackH408

📖 Shubham
Shubham

🌍 + Nishant Jain
Nishant Jain

📖 From 4d9b8b4d0fa34dd31deb3f273d50c56806a25cbb Mon Sep 17 00:00:00 2001 From: Rhitam Chaudhury <90751158+hallowshaw@users.noreply.github.com> Date: Sun, 15 Oct 2023 19:14:18 +0530 Subject: [PATCH 24/26] docs: Object Mother explanation (#2634) --- object-mother/README.md | 65 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/object-mother/README.md b/object-mother/README.md index 99d49af4b04d..4f2a6664cd48 100644 --- a/object-mother/README.md +++ b/object-mother/README.md @@ -7,7 +7,7 @@ tag: --- ## Object Mother -Define a factory of immutable content with separated builder and factory interfaces. +It is used to define a factory of immutable content with separated builder and factory interfaces. ## Class diagram ![alt text](./etc/object-mother.png "Object Mother") @@ -19,6 +19,69 @@ Use the Object Mother pattern when * You want to reduce code for creation of objects in tests * Every test should run with fresh data + +## Understanding the Object Mother Pattern + +### Real-World Scenario +Imagine you're developing a Java application for a travel agency. In your system, there are different types of travelers, such as tourists, business travelers, and travel agents, each with specific attributes and behaviors. To perform thorough testing, you need to create and manipulate these traveler objects in various contexts. The Object Mother Pattern can help you generate consistent and predefined traveler objects for testing purposes, ensuring that your tests are based on known, reliable data. + +### In Plain Terms +The Object Mother Pattern is a design pattern used in Java to simplify the creation of objects with specific configurations, especially for testing. Instead of manually constructing objects with varying properties for each test case, you create a dedicated "Object Mother" class or method that produces these objects with predefined settings. This ensures that you have consistent and predictable test data, making your tests more reliable and easier to manage. + +### Overview from a Testing Perspective +The Object Mother Pattern is a testing-related design pattern that assists in maintaining a consistent and reliable testing environment. It allows you to define and create objects with specific attributes, helping you ensure that your tests produce consistent and predictable results, making it easier to spot issues and maintain your test suite. + +### Practical Usage in Testing +In software testing, especially unit testing, the Object Mother Pattern is invaluable. It helps ensure that your tests are not influenced by unpredictable data, thus making your tests more robust and repeatable. By centralizing the creation of test objects in an Object Mother, you can easily adapt your test data to different scenarios. + +### Example in Java +Here's an illustrative Java example of the Object Mother Pattern within the context of a travel agency application: + +```java +class Traveler { + private String name; + private int age; + private boolean isBusinessTraveler; + + // Constructor and methods for the traveler + // ... + + // Getter and setter methods + // ... +} + +class TravelerMother { + public static Traveler createTourist(String name, int age) { + Traveler traveler = new Traveler(); + traveler.setName(name); + traveler.setAge(age); + traveler.setBusinessTraveler(false); + return traveler; + } + + public static Traveler createBusinessTraveler(String name, int age) { + Traveler traveler = new Traveler(); + traveler.setName(name); + traveler.setAge(age); + traveler.setBusinessTraveler(true); + return traveler; + } +} + +public class TravelAgency { + public static void main(String[] args) { + // Using the Object Mother to create traveler objects for testing + Traveler tourist = TravelerMother.createTourist("Alice", 28); + Traveler businessTraveler = TravelerMother.createBusinessTraveler("Bob", 35); + + // Now you have consistent traveler objects for testing. + } +} + +``` + +In this example, TravelerMother is the Object Mother class responsible for generating predefined Traveler objects with specific configurations. This approach ensures that you have consistent test data for various scenarios in a travel agency application, enhancing the reliability and effectiveness of your testing efforts. + ## Credits * [Answer by David Brown](http://stackoverflow.com/questions/923319/what-is-an-objectmother) to the stackoverflow question: [What is an ObjectMother?](http://stackoverflow.com/questions/923319/what-is-an-objectmother) From f63c5dd46ddaaeaa6c2844dd7db6192fafce616a Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 16:45:17 +0300 Subject: [PATCH 25/26] docs: add hallowshaw as a contributor for doc (#2661) * 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 ea3d134770c1..8ae01fac1c43 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2715,6 +2715,15 @@ "contributions": [ "doc" ] + }, + { + "login": "hallowshaw", + "name": "Rhitam Chaudhury", + "avatar_url": "https://avatars.githubusercontent.com/u/90751158?v=4", + "profile": "https://github.com/hallowshaw", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 662a8a57e10c..32b3bacc1073 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-298-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-299-orange.svg?style=flat-square)](#contributors-)
@@ -458,6 +458,7 @@ This project is licensed under the terms of the MIT license. JackH408
JackH408

📖 Shubham
Shubham

🌍 Nishant Jain
Nishant Jain

📖 + Rhitam Chaudhury
Rhitam Chaudhury

📖 From b71eea4b4e4849e593b8d7e23bb0cbbb6404955c Mon Sep 17 00:00:00 2001 From: Allagadda Sai Upendranath Date: Sun, 22 Oct 2023 23:19:37 +0530 Subject: [PATCH 26/26] docs: Update README.md (#2614) Fixes #2263 Explanation for Step Builder. Updating Readme.md of Step Builder. --- step-builder/README.md | 88 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/step-builder/README.md b/step-builder/README.md index 659da6e31968..a1e98b237611 100644 --- a/step-builder/README.md +++ b/step-builder/README.md @@ -6,16 +6,100 @@ tag: - Instantiation --- +# Step Builder Pattern + +## Explanation + +The Step Builder pattern is a creational design pattern used to construct a complex object step by step. It provides a fluent interface to create an object with a large number of possible configurations, making the code more readable and reducing the need for multiple constructors or setter methods. + ## Intent An extension of the Builder pattern that fully guides the user through the creation of the object with no chances of confusion. The user experience will be much more improved by the fact that he will only see the next step methods available, NO build method until is the right time to build the object. -## Class diagram -![alt text](./etc/step-builder.png "Step Builder") +## Real World Example + +Imagine you are building a configuration object for a database connection. The connection has various optional parameters such as host, port, username, password, and others. Using the Step Builder pattern, you can set these parameters in a clean and readable way: + +```java +DatabaseConnection connection = new DatabaseConnection.Builder() + .setHost("localhost") + .setPort(3306) + .setUsername("user") + .setPassword("password") + .setSSL(true) + .build(); +``` + +## In Plain Words + +The Step Builder pattern allows you to construct complex objects by breaking down the construction process into a series of steps. Each step corresponds to setting a particular attribute or configuration option of the object. This results in more readable and maintainable code, especially when dealing with objects that have numerous configuration options. + +## Wikipedia Says + +According to Wikipedia, the Step Builder pattern is a creational design pattern in which an object is constructed step by step. It involves a dedicated 'director' class, which orchestrates the construction process through a series of 'builder' classes, each responsible for a specific aspect of the object's configuration. This pattern is particularly useful when dealing with objects that have a large number of optional parameters. + +## Programmatic Example + +Assuming you have a class `Product` with several configurable attributes, a Step Builder for it might look like this: + +```java +public class Product { + private String name; + private double price; + private int quantity; + + // private constructor to force the use of the builder + private Product(String name, double price, int quantity) { + + this.name = name; + this.price = price; + this.quantity = quantity; + + } + + public static class Builder { + private String name; + private double price; + private int quantity; + + public Builder setName(String name) { + this.name = name; + return this; + } + + public Builder setPrice(double price) { + this.price = price; + return this; + } + + public Builder setQuantity(int quantity) { + this.quantity = quantity; + return this; + } + + public Product build() { + return new Product(name, price, quantity); + } + } +} + +// Usage +Product product = new Product.Builder() + .setName("Example Product") + .setPrice(29.99) + .setQuantity(100) + .build(); +``` + +This example demonstrates how you can use the Step Builder pattern to create a `Product` object with a customizable set of attributes. Each method in the builder corresponds to a step in the construction process. ## Applicability Use the Step 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 when in the process of constructing the order is important. +## Another example with class diagram +![alt text](./etc/step-builder.png "Step Builder") + + ## Credits * [Marco Castigliego - Step Builder](http://rdafbn.blogspot.co.uk/2012/07/step-builder-pattern_28.html)