docs: add diagrams for decorator, delegation, dependency injection, dirty flag, domain model, double buffer, double-checked locking, double dispatch, and dynamic proxy

This commit is contained in:
Ilkka Seppälä
2025-04-06 15:52:26 +03:00
parent 203548ec03
commit 30d13083ae
18 changed files with 36 additions and 12 deletions
+4
View File
@@ -35,6 +35,10 @@ Wikipedia says
> In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern as well as to the Open-Closed Principle, by allowing the functionality of a class to be extended without being modified.
Sequence diagram
![Decorator sequence diagram](./etc/decorator-sequence-diagram.png)
## Programmatic Example of Decorator Pattern in Java
There is an angry troll living in the nearby hills. Usually, it goes bare-handed, but sometimes it has a weapon. To arm the troll it's not necessary to create a new troll but to decorate it dynamically with a suitable weapon.
Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

+4 -4
View File
@@ -33,6 +33,10 @@ Wikipedia says
> In object-oriented programming, delegation refers to evaluating a member (property or method) of one object (the receiver) in the context of another original object (the sender). Delegation can be done explicitly, by passing the sending object to the receiving object, which can be done in any object-oriented language; or implicitly, by the member lookup rules of the language, which requires language support for the feature.
Sequence diagram
![Delegation sequence diagram](./etc/delegation-sequence-diagram.png)
## Programmatic Example of Delegation Pattern in Java
Let's consider a printing example.
@@ -114,10 +118,6 @@ Canon Printer:hello world
Epson Printer:hello world
```
## Detailed Explanation of Delegation Pattern with Real-World Examples
![Delegate class diagram](./etc/delegation.png "Delegate")
## When to Use the Delegation Pattern in Java
* When you want to pass responsibility from one class to another without inheritance.
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+4
View File
@@ -35,6 +35,10 @@ Wikipedia says
> In software engineering, dependency injection is a technique in which an object receives other objects that it depends on. These other objects are called dependencies.
Sequence diagram
![Dependency Injection sequence diagram](./etc/dependency-injection-sequence-diagram.png)
## Programmatic Example of Dependency Injection Pattern in Java
The old wizard likes to fill his pipe and smoke tobacco once in a while. However, he doesn't want to depend on a single tobacco brand only but likes to be able to enjoy them all interchangeably.
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+4
View File
@@ -34,6 +34,10 @@ Wikipedia says
> A dirty bit or modified bit is a bit that is associated with a block of computer memory and indicates whether the corresponding block of memory has been modified. The dirty bit is set when the processor writes to (modifies) this memory. The bit indicates that its associated block of memory has been modified and has not been saved to storage yet. When a block of memory is to be replaced, its corresponding dirty bit is checked to see if the block needs to be written back to secondary memory before being replaced or if it can simply be removed. Dirty bits are used by the CPU cache and in the page replacement algorithms of an operating system.
Flowchart
![Dirty Flag flowchart](./etc/dirty-flag-flowchart.png)
## Programmatic Example of Dirty Flag Pattern in Java
The `DataFetcher` class is responsible for fetching data from a file. It has a dirty flag that indicates whether the data in the file has changed since the last fetch.
Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

+4 -4
View File
@@ -34,6 +34,10 @@ In plain words
> The Domain Model is an object model of the domain that incorporates both behavior and data.
Mind map
![Domain Model mind map](./etc/domain-model-mind-map.png)
## Programmatic Example of Domain Model Pattern in Java
Let's assume that we need to build an e-commerce web application. While analyzing requirements you will notice that there are few nouns you talk about repeatedly. Its your Customer, and a Product the customer looks for. These two are your domain-specific classes and each of that classes will include some business logic specific to its domain.
@@ -225,10 +229,6 @@ The program output:
12:17:23.846 [main] INFO com.iluwatar.domainmodel.Customer -- Tom bought: Eggs - $10.00, Cheese - $20.00
```
## Detailed Explanation of Domain Model Pattern with Real-World Examples
![Domain Model class diagram](./etc/domain-model.urm.png "Domain Model")
## When to Use the Domain Model Pattern in Java
* Appropriate in complex applications with rich business logic.
Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

+4
View File
@@ -34,6 +34,10 @@ Wikipedia says
> In computer science, multiple buffering is the use of more than one buffer to hold a block of data, so that a "reader" will see a complete (though perhaps old) version of the data, rather than a partially updated version of the data being created by a "writer". It is very commonly used for computer display images.
Sequence diagram
![Double Buffer sequence diagram](./etc/double-buffer-sequence-diagram.png)
## Programmatic Example of Double Buffer Pattern in Java
A typical example, and one that every game engine must address, is rendering. When the game draws the world the users see, it does so one piece at a time - the mountains in the distance, the rolling hills, the trees, each in its turn. If the user watched the view draw incrementally like that, the illusion of a coherent world would be shattered. The scene must update smoothly and quickly, displaying a series of complete frames, each appearing instantly. Double buffering solves the problem.
Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

+4
View File
@@ -29,6 +29,10 @@ Wikipedia says
> In software engineering, double-checked locking (also known as "double-checked locking optimization") is a software design pattern used to reduce the overhead of acquiring a lock by testing the locking criterion (the "lock hint") before acquiring the lock. Locking occurs only if the locking criterion check indicates that locking is required.
Flowchart
![Double-Checked Locking flowchart](./etc/double-checked-locking-flowchart.png)
## Programmatic Example of Double-Checked Locking Pattern in Java
The Double-Checked Locking pattern is used in the `HolderThreadSafe` class to ensure that the `Heavy` object is only created once, even when accessed from multiple threads. Here's how it works:
Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

+4 -4
View File
@@ -33,6 +33,10 @@ Wikipedia says
> In software engineering, double dispatch is a special form of multiple dispatch, and a mechanism that dispatches a function call to different concrete functions depending on the runtime types of two objects involved in the call. In most object-oriented systems, the concrete function that is called from a function call in the code depends on the dynamic type of a single object and therefore they are known as single dispatch calls, or simply virtual function calls.
Sequence diagram
![Double Dispatch sequence diagram](./etc/double-dispatch-sequence-diagram.png)
## Programmatic Example of Double Dispatch Pattern in Java
The Double Dispatch pattern in Java is used to handle collisions between different types of game objects. Each game object is an instance of a class that extends the `GameObject` abstract class. The `GameObject` class has a `collision(GameObject)` method, which is overridden in each subclass to define the behavior when a collision occurs with another game object. Here is a simplified version of the `GameObject` class and its subclasses:
@@ -113,10 +117,6 @@ Here is the program output:
15:47:23.773 [main] INFO com.iluwatar.doubledispatch.App -- SpaceStationIss at [12,12,14,14] damaged=true onFire=false
```
## Detailed Explanation of Double Dispatch Pattern with Real-World Examples
![Double Dispatch](./etc/double-dispatch.png "Double Dispatch")
## When to Use the Double Dispatch Pattern in Java
* When the behavior of a method needs to vary not just based on the object it is called on, but also based on the type of the argument.
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+4
View File
@@ -35,6 +35,10 @@ Wikipedia says
> A dynamic proxy class is a class that implements a list of interfaces specified at runtime such that a method invocation through one of the interfaces on an instance of the class will be encoded and dispatched to another object through a uniform interface. Thus, a dynamic proxy class can be used to create a type-safe proxy object for a list of interfaces without requiring pre-generation of the proxy class, such as with compile-time tools. Method invocations on an instance of a dynamic proxy class are dispatched to a single method in the instance's invocation handler, and they are encoded with a _java.lang.reflect.Method_ object identifying the method that was invoked and an array of type _Object_ containing the arguments.
Sequence diagram
![Dynamic Proxy sequence diagram](./etc/dynamic-proxy-sequence-diagram.png)
## Programmatic Example of Dynamic Proxy Pattern in Java
This example demonstrates using the Dynamic Proxy pattern in Java to hit the public fake API [JSONPlaceholder](https://jsonplaceholder.typicode.com) for the resource `Album` through an interface.
Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB