Skip to content

Commit 584e949

Browse files
committed
docs: updates to several patterns
1 parent 4652842 commit 584e949

File tree

70 files changed

+344
-476
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+344
-476
lines changed

abstract-document/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ The Abstract Document design pattern is a structural design pattern that aims to
1919

2020
The Abstract Document pattern enables handling additional, non-static properties. This pattern uses concept of traits to enable type safety and separate properties of different classes into set of interfaces.
2121

22-
Real world example
22+
Real-world example
2323

2424
> Imagine a library system where books can have different formats and attributes: physical books, eBooks, and audiobooks. Each format has unique properties, such as page count for physical books, file size for eBooks, and duration for audiobooks. The Abstract Document design pattern allows the library system to manage these diverse formats flexibly. By using this pattern, the system can store and retrieve properties dynamically, without needing a rigid structure for each book type, making it easier to add new formats or attributes in the future without significant changes to the codebase.
2525

active-object/README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,21 +99,20 @@ public abstract class ActiveCreature {
9999
}
100100
```
101101

102-
We can see that any class that will extend the ActiveCreature class will have its own thread of control to invoke and execute methods.
102+
We can see that any class that will extend the `ActiveCreature` class will have its own thread of control to invoke and execute methods.
103103

104-
For example, the Orc class:
104+
For example, the `Orc` class:
105105

106106
```java
107107
public class Orc extends ActiveCreature {
108108

109109
public Orc(String name) {
110110
super(name);
111111
}
112-
113112
}
114113
```
115114

116-
Now, we can create multiple creatures such as Orcs, tell them to eat and roam, and they will execute it on their own thread of control:
115+
Now, we can create multiple creatures such as orcs, tell them to eat and roam, and they will execute it on their own thread of control:
117116

118117
```java
119118
public class App implements Runnable {

acyclic-visitor/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ The Acyclic Visitor pattern decouples operations from an object hierarchy, allow
1515

1616
## Explanation
1717

18-
Real world example
18+
Real-world example
1919

2020
> An analogous real-world example of the Acyclic Visitor pattern is a museum guide system. Imagine a museum with various exhibits like paintings, sculptures, and historical artifacts. The museum has different types of guides (audio guide, human guide, virtual reality guide) that provide information about each exhibit. Instead of modifying the exhibits every time a new guide type is introduced, each guide implements an interface to visit different exhibit types. This way, the museum can add new types of guides without altering the existing exhibits, ensuring that the system remains extensible and maintainable without forming any dependency cycles.
2121

adapter/README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,6 @@ The program outputs:
106106
10:25:08.074 [main] INFO com.iluwatar.adapter.FishingBoat -- The fishing boat is sailing
107107
```
108108

109-
## Class diagram
110-
111-
![Adapter](./etc/adapter.urm.png "Adapter class diagram")
112-
113109
## Applicability
114110

115111
Use the Adapter pattern when

aggregator-microservices/README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ To aggregate responses from multiple microservices and return a consolidated res
1818

1919
## Explanation
2020

21-
Real world example
21+
Real-world example
2222

2323
> Imagine an online travel booking platform. When a user searches for a vacation package, the platform needs to gather information from several different services: flights, hotels, car rentals, and local attractions. Instead of the user making separate requests to each service, the platform employs an Aggregator Microservice. This microservice calls each of these services, collects their responses, and then consolidates the information into a single, unified response that is sent back to the user. This simplifies the user experience by providing all necessary travel details in one place and reduces the number of direct interactions the user needs to have with the underlying services.
2424
@@ -98,10 +98,6 @@ curl http://localhost:50004/product
9898
{"title":"The Product Title.","productInventories":5}
9999
```
100100

101-
## Class diagram
102-
103-
![Class diagram of the Aggregator Microservices Pattern](./aggregator-service/etc/aggregator-service.png "Aggregator Microservice")
104-
105101
## Applicability
106102

107103
The Aggregator Microservices Design Pattern is particularly useful in scenarios where a client requires a composite response that is assembled from data provided by multiple microservices. Common use cases include e-commerce applications where product details, inventory, and reviews might be provided by separate services, or in dashboard applications where aggregated data from various services is displayed in a unified view.

ambassador/README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Provide a helper service instance on a client and offload common functionality a
2121

2222
## Explanation
2323

24-
Real world example
24+
Real-world example
2525

2626
> Imagine a busy hotel where guests frequently request restaurant reservations, event tickets, or transportation arrangements. Instead of each guest individually contacting these services, the hotel provides a concierge. The concierge handles these tasks on behalf of the guests, ensuring that reservations are made smoothly, tickets are booked on time, and transportation is scheduled efficiently.
2727
>
@@ -175,10 +175,6 @@ Failed to reach remote:(3)
175175
Service result:-1
176176
```
177177

178-
## Class diagram
179-
180-
![Ambassador](./etc/ambassador.urm.png "Ambassador class diagram")
181-
182178
## Applicability
183179

184180
* Cloud Native and Microservices Architectures: Especially useful in distributed systems where it's crucial to monitor, log, and secure inter-service communication.

anti-corruption-layer/README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,6 @@ public class LegacyShop {
129129
}
130130
```
131131

132-
## Class diagram
133-
134-
![Anti-Corruption Layer](./etc/anti-corruption-layer.urm.png "Anti-Corruption Layer class diagram")
135-
136132
## Applicability
137133

138134
Use this pattern when:

api-gateway/README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ The API Gateway design pattern aims to provide a unified interface to a set of m
2424

2525
## Explanation
2626

27-
Real world example
27+
Real-world example
2828

2929
> In a large e-commerce platform, an API Gateway is used as the single entry point for all client requests. When a user visits the site or uses the mobile app, their requests for product information, user authentication, order processing, and payment are all routed through the API Gateway. The gateway handles tasks such as user authentication, rate limiting to prevent abuse, and logging for monitoring purposes. This setup simplifies the client interface and ensures that all backend microservices, like the product catalog service, user service, order service, and payment service, can evolve independently without affecting the client directly. This also enhances security by providing a centralized point to enforce policies and monitor traffic.
3030
@@ -125,10 +125,6 @@ public class ApiGateway {
125125
}
126126
```
127127

128-
## Class diagram
129-
130-
![API Gateway](./etc/api-gateway.png "API Gateway")
131-
132128
## Applicability
133129

134130
* When building a microservices architecture, and there's a need to abstract the complexity of microservices from the client.

async-method-invocation/README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,6 @@ Here's the program console output.
153153
21:47:08.618[main]INFO com.iluwatar.async.method.invocation.App-Space rocket<50>launch complete
154154
```
155155

156-
# Class diagram
157-
158-
![Async Method Invocation](./etc/async-method-invocation.urm.png "Async Method Invocation")
159-
160156
## Applicability
161157

162158
Use the async method invocation pattern when

balking/README.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Balking Pattern is used to prevent an object from executing a certain code if it
1515

1616
## Explanation
1717

18-
Real world example
18+
Real-world example
1919

2020
> A real-world analogy of the Balking design pattern can be seen in a laundry service. Imagine a washing machine at a laundromat that only starts washing clothes if the door is properly closed and locked. If a user tries to start the machine while the door is open, the machine balks and does nothing. This ensures that the washing process only begins when it is safe to do so, preventing water spillage and potential damage to the machine. Similarly, the Balking pattern in software design ensures that operations are only executed when the object is in an appropriate state, preventing erroneous actions and maintaining system stability.
2121
@@ -31,7 +31,7 @@ Wikipedia says
3131

3232
There's a start-button in a washing machine to initiate the laundry washing. When the washing machine is inactive the button works as expected, but if it's already washing the button does nothing.
3333

34-
In this example implementation, `WashingMachine` is an object that has two states in which it can be: ENABLED and WASHING. If the machine is ENABLED, the state changes to WASHING using a thread-safe method. On the other hand, if it already has been washing and any other thread executes `wash()`it won't do that and returns without doing anything.
34+
In this example implementation, `WashingMachine` is an object that has two states in which it can be: ENABLED and WASHING. If the machine is ENABLED, the state changes to WASHING using a thread-safe method. On the other hand, if it already has been washing and any other thread executes `wash`it won't do that and returns without doing anything.
3535

3636
Here are the relevant parts of the `WashingMachine` class.
3737

@@ -114,10 +114,6 @@ Here is the console output of the program.
114114
14:02:52.324 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - 14: Washing completed.
115115
```
116116

117-
## Class diagram
118-
119-
![Balking](./etc/balking.png "Balking")
120-
121117
## Applicability
122118

123119
Use the Balking pattern when

bridge/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Wikipedia says
3636
3737
**Programmatic Example**
3838

39-
Consider you have a weapon with different enchantments, and you are supposed to allow mixing different weapons with different enchantments. What would you do? Create multiple copies of each of the weapons for each of the enchantments or would you just create separate enchantment and set it for the weapon as needed? Bridge pattern allows you to do the second.
39+
Imagine you have a weapon that can have various enchantments, and you need to combine different weapons with different enchantments. How would you handle this? Would you create multiple copies of each weapon, each with a different enchantment, or would you create separate enchantments and apply them to the weapon as needed? The Bridge pattern enables you to do the latter.
4040

4141
Here we have the `Weapon` hierarchy:
4242

@@ -116,7 +116,7 @@ public class Hammer implements Weapon {
116116
}
117117
```
118118

119-
Here's the separate enchantment hierarchy:
119+
Here's the separate `Enchantment` hierarchy:
120120

121121
```java
122122
public interface Enchantment {

builder/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,21 @@ Wikipedia says
2626

2727
> The builder pattern is an object creation software design pattern with the intentions of finding a solution to the telescoping constructor antipattern.
2828
29-
That said, let's clarify what telescoping constructor antipattern is. At one point or the other, we have all seen a constructor like below:
29+
With that in mind, let's explain what the telescoping constructor antipattern is. At some point, we have all encountered a constructor like the one below:
3030

3131
```java
3232
public Hero(Profession profession,String name,HairType hairType,HairColor hairColor,Armor armor,Weapon weapon){
3333
// Value assignments
3434
}
3535
```
3636

37-
As you can see the number of constructor parameters can quickly get out of hand, and it may become difficult to understand the arrangement of parameters. Plus this parameter list could keep on growing if you would want to add more options in the future. This is called telescoping constructor antipattern.
37+
As you can see, the number of constructor parameters can quickly become overwhelming, making it difficult to understand their arrangement. Additionally, this list of parameters might continue to grow if you decide to add more options in the future. This is known as the telescoping constructor antipattern.
3838

3939
**Programmatic Example**
4040

41-
Imagine a character generator for a role-playing game. The easiest option is to let the computer create the character for you. If you want to manually select the character details like profession, gender, hair color, etc. the character generation becomes a step-by-step process that completes when all the selections are ready.
41+
Imagine a character generator for a role-playing game. The simplest option is to let the computer generate the character for you. However, if you prefer to manually select character details such as profession, gender, hair color, etc., the character creation becomes a step-by-step process that concludes once all selections are made.
4242

43-
The sane alternative is to use the Builder pattern. First of all, we have our hero that we want to create:
43+
A more sensible approach is to use the Builder pattern. First, let's consider the `Hero` that we want to create:
4444

4545
```java
4646
public final class Hero {
@@ -62,7 +62,7 @@ public final class Hero {
6262
}
6363
```
6464

65-
Then we have the builder:
65+
Then we have the `Builder`:
6666

6767
```java
6868
public static class Builder {

bytecode/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Allows encoding behavior as instructions for a virtual machine.
1717

1818
## Explanation
1919

20-
Real world example
20+
Real-world example
2121

2222
> An analogous real-world example of the Bytecode design pattern can be seen in the process of translating a book into multiple languages. Instead of directly translating the book from the original language into every other language, the book is first translated into a common intermediate language, like Esperanto. This intermediate version is easier to translate because it is simpler and more structured. Translators for each target language then translate from Esperanto into their specific languages. This approach ensures consistency, reduces errors, and simplifies the translation process, similar to how bytecode serves as an intermediate representation to optimize and facilitate the execution of high-level programming languages across different platforms.
2323

caching/README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ In plain words
2828

2929
> Caching pattern keeps frequently needed data in fast-access storage to improve performance.
3030
31-
Wikipedia says:
31+
Wikipedia says
3232

3333
> In computing, a cache is a hardware or software component that stores data so that future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation or a copy of data stored elsewhere. A cache hit occurs when the requested data can be found in a cache, while a cache miss occurs when it cannot. Cache hits are served by reading data from the cache, which is faster than recomputing a result or reading from a slower data store; thus, the more requests that can be served from the cache, the faster the system performs.
3434
@@ -419,10 +419,6 @@ UserAccount(userId=003, userName=Adam, additionalInfo=He likes food.)
419419
17:00:56.314 [Thread-0] INFO com.iluwatar.caching.CacheStore -- # flushCache...
420420
```
421421

422-
## Class diagram
423-
424-
![Caching](./etc/caching.png "Caching")
425-
426422
## Applicability
427423

428424
Use the Caching pattern when

callback/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Callback is a piece of executable code that is passed as an argument to other co
2121

2222
## Explanation
2323

24-
Real world example
24+
Real-world example
2525

2626
> A real-world analogy for the Callback design pattern can be found in the restaurant industry. Imagine a situation where you place an order at a busy restaurant. Instead of waiting at the counter for your food to be ready, you provide the cashier with your phone number. Once your order is prepared, the kitchen staff calls or sends a text message to notify you that your meal is ready for pickup.
2727
>
@@ -39,7 +39,7 @@ Wikipedia says
3939

4040
We need to be notified after the executing task has finished. We pass a callback method for the executor and wait for it to call back on us.
4141

42-
Callback is a simple interface with single method.
42+
`Callback` is a simple interface with single method.
4343

4444
```java
4545
public interface Callback {
@@ -48,7 +48,7 @@ public interface Callback {
4848
}
4949
```
5050

51-
Next we define a task that will execute the callback after the task execution has finished.
51+
Next we define `Task` that will execute the callback after the task execution has finished.
5252

5353
```java
5454
public abstract class Task {

chain-of-responsibility/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public enum RequestType {
6767
}
6868
```
6969

70-
Next, we show the request handler hierarchy.
70+
Next, we show the `RequestHandler` hierarchy.
7171

7272
```java
7373
public interface RequestHandler {
@@ -109,7 +109,7 @@ public class OrcCommander implements RequestHandler {
109109

110110
```
111111

112-
The Orc King gives the orders and forms the chain.
112+
The `OrcKing` gives the orders and forms the chain.
113113

114114
```java
115115
public class OrcKing {

circuit-breaker/README.md

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,57 @@ LOGGER.info(monitoringService.delayedServiceResponse());
9595
LOGGER.info(delayedServiceCircuitBreaker.getState());
9696
```
9797

98+
6. **Full example**
99+
100+
```java
101+
public static void main(String[] args) {
102+
103+
var serverStartTime = System.nanoTime();
104+
105+
var delayedService = new DelayedRemoteService(serverStartTime, 5);
106+
var delayedServiceCircuitBreaker = new DefaultCircuitBreaker(delayedService, 3000, 2,
107+
2000 * 1000 * 1000);
108+
109+
var quickService = new QuickRemoteService();
110+
var quickServiceCircuitBreaker = new DefaultCircuitBreaker(quickService, 3000, 2,
111+
2000 * 1000 * 1000);
112+
113+
//Create an object of monitoring service which makes both local and remote calls
114+
var monitoringService = new MonitoringService(delayedServiceCircuitBreaker,
115+
quickServiceCircuitBreaker);
116+
117+
//Fetch response from local resource
118+
LOGGER.info(monitoringService.localResourceResponse());
119+
120+
//Fetch response from delayed service 2 times, to meet the failure threshold
121+
LOGGER.info(monitoringService.delayedServiceResponse());
122+
LOGGER.info(monitoringService.delayedServiceResponse());
123+
124+
//Fetch current state of delayed service circuit breaker after crossing failure threshold limit
125+
//which is OPEN now
126+
LOGGER.info(delayedServiceCircuitBreaker.getState());
127+
128+
//Meanwhile, the delayed service is down, fetch response from the healthy quick service
129+
LOGGER.info(monitoringService.quickServiceResponse());
130+
LOGGER.info(quickServiceCircuitBreaker.getState());
131+
132+
//Wait for the delayed service to become responsive
133+
try {
134+
LOGGER.info("Waiting for delayed service to become responsive");
135+
Thread.sleep(5000);
136+
} catch (InterruptedException e) {
137+
LOGGER.error("An error occurred: ", e);
138+
}
139+
//Check the state of delayed circuit breaker, should be HALF_OPEN
140+
LOGGER.info(delayedServiceCircuitBreaker.getState());
141+
142+
//Fetch response from delayed service, which should be healthy by now
143+
LOGGER.info(monitoringService.delayedServiceResponse());
144+
//As successful response is fetched, it should be CLOSED again.
145+
LOGGER.info(delayedServiceCircuitBreaker.getState());
146+
}
147+
```
148+
98149
Summary of the example
99150

100151
- Initialize the Circuit Breaker with parameters: `timeout`, `failureThreshold`, and `retryTimePeriod`.
@@ -104,11 +155,22 @@ Summary of the example
104155
- After the retry timeout, transition to the `half-open` state to test the service.
105156
- On success in `half-open` state, transition back to `closed`. On failure, return to `open`.
106157

107-
This example demonstrates how the Circuit Breaker pattern can help maintain application stability and resilience by managing remote service failures.
158+
Program output:
108159

109-
## Class diagram
160+
```
161+
16:59:19.767 [main] INFO com.iluwatar.circuitbreaker.App -- Local Service is working
162+
16:59:19.769 [main] INFO com.iluwatar.circuitbreaker.App -- Delayed service is down
163+
16:59:19.769 [main] INFO com.iluwatar.circuitbreaker.App -- Delayed service is down
164+
16:59:19.769 [main] INFO com.iluwatar.circuitbreaker.App -- OPEN
165+
16:59:19.769 [main] INFO com.iluwatar.circuitbreaker.App -- Quick Service is working
166+
16:59:19.769 [main] INFO com.iluwatar.circuitbreaker.App -- CLOSED
167+
16:59:19.769 [main] INFO com.iluwatar.circuitbreaker.App -- Waiting for delayed service to become responsive
168+
16:59:24.779 [main] INFO com.iluwatar.circuitbreaker.App -- HALF_OPEN
169+
16:59:24.780 [main] INFO com.iluwatar.circuitbreaker.App -- Delayed service is working
170+
16:59:24.780 [main] INFO com.iluwatar.circuitbreaker.App -- CLOSED
171+
```
110172

111-
![Circuit Breaker](./etc/circuit-breaker.urm.png "Circuit Breaker class diagram")
173+
This example demonstrates how the Circuit Breaker pattern can help maintain application stability and resilience by managing remote service failures.
112174

113175
## Applicability
114176

0 commit comments

Comments
 (0)