mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-10-14 12:16:46 +00:00
docs: update .editorconfig and reformat readmes
This commit is contained in:
1 parent
dfd34d890b
commit
de5a93c499
31 files changed
+387
-985
No files matched your search
+2
-1
@@ -31,7 +31,7 @@ end_of_line = lf
|
|||||||
indent_size = 4
|
indent_size = 4
|
||||||
indent_style = space
|
indent_style = space
|
||||||
insert_final_newline = false
|
insert_final_newline = false
|
||||||
max_line_length = 120
|
max_line_length = off
|
||||||
tab_width = 4
|
tab_width = 4
|
||||||
ij_continuation_indent_size = 8
|
ij_continuation_indent_size = 8
|
||||||
ij_formatter_off_tag = @formatter:off
|
ij_formatter_off_tag = @formatter:off
|
||||||
@@ -355,6 +355,7 @@ ij_markdown_format_tables = true
|
|||||||
ij_markdown_insert_quote_arrows_on_wrap = true
|
ij_markdown_insert_quote_arrows_on_wrap = true
|
||||||
ij_markdown_keep_indents_on_empty_lines = false
|
ij_markdown_keep_indents_on_empty_lines = false
|
||||||
ij_markdown_keep_line_breaks_inside_text_blocks = true
|
ij_markdown_keep_line_breaks_inside_text_blocks = true
|
||||||
|
ij_markdown_max_line_length = off
|
||||||
ij_markdown_max_lines_around_block_elements = 1
|
ij_markdown_max_lines_around_block_elements = 1
|
||||||
ij_markdown_max_lines_around_header = 1
|
ij_markdown_max_lines_around_header = 1
|
||||||
ij_markdown_max_lines_between_paragraphs = 1
|
ij_markdown_max_lines_between_paragraphs = 1
|
||||||
|
|||||||
+15
-44
@@ -10,19 +10,15 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Abstract Document design pattern is a structural design pattern that aims to provide a consistent way to handle
|
The Abstract Document design pattern is a structural design pattern that aims to provide a consistent way to handle hierarchical and tree-like data structures by defining a common interface for various document types. It separates the core document structure from specific data formats, enabling dynamic updates and simplified maintenance.
|
||||||
hierarchical and tree-like data structures by defining a common interface for various document types. It separates the
|
|
||||||
core document structure from specific data formats, enabling dynamic updates and simplified maintenance.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
The Abstract Document pattern enables handling additional, non-static properties. This pattern uses concept of traits to
|
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.
|
||||||
enable type safety and separate properties of different classes into set of interfaces.
|
|
||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> Consider a car that consists of multiple parts. However, we don't know if the specific car really has all the parts,
|
> Consider a car that consists of multiple parts. However, we don't know if the specific car really has all the parts, or just some of them. Our cars are dynamic and extremely flexible.
|
||||||
> or just some of them. Our cars are dynamic and extremely flexible.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
@@ -30,15 +26,11 @@ In plain words
|
|||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> An object-oriented structural design pattern for organizing objects in loosely typed key-value stores and exposing the
|
> An object-oriented structural design pattern for organizing objects in loosely typed key-value stores and exposing the data using typed views. The purpose of the pattern is to achieve a high degree of flexibility between components in a strongly typed language where new properties can be added to the object-tree on the fly, without losing the support of type-safety. The pattern makes use of traits to separate different properties of a class into different interfaces.
|
||||||
> data using typed views. The purpose of the pattern is to achieve a high degree of flexibility between components in a
|
|
||||||
> strongly typed language where new properties can be added to the object-tree on the fly, without losing the support of
|
|
||||||
> type-safety. The pattern makes use of traits to separate different properties of a class into different interfaces.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
Let's first define the base classes `Document` and `AbstractDocument`. They basically make the object hold a property
|
Let's first define the base classes `Document` and `AbstractDocument`. They basically make the object hold a property map and any amount of child objects.
|
||||||
map and any amount of child objects.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public interface Document {
|
public interface Document {
|
||||||
@@ -84,8 +76,7 @@ public abstract class AbstractDocument implements Document {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Next we define an enum `Property` and a set of interfaces for type, price, model and parts. This allows us to create
|
Next we define an enum `Property` and a set of interfaces for type, price, model and parts. This allows us to create static looking interface to our `Car` class.
|
||||||
static looking interface to our `Car` class.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public enum Property {
|
public enum Property {
|
||||||
@@ -180,38 +171,21 @@ And finally here's how we construct and use the `Car` in a full example.
|
|||||||
|
|
||||||
## Applicability
|
## Applicability
|
||||||
|
|
||||||
This pattern is particularly useful in scenarios where you have different types of documents that share some common
|
This pattern is particularly useful in scenarios where you have different types of documents that share some common attributes or behaviors, but also have unique attributes or behaviors specific to their individual types. Here are some scenarios where the Abstract Document design pattern can be applicable:
|
||||||
attributes or behaviors, but also have unique attributes or behaviors specific to their individual types. Here are some
|
|
||||||
scenarios where the Abstract Document design pattern can be applicable:
|
|
||||||
|
|
||||||
* Content Management Systems (CMS): In a CMS, you might have various types of content such as articles, images, videos,
|
* Content Management Systems (CMS): In a CMS, you might have various types of content such as articles, images, videos, etc. Each type of content could have shared attributes like creation date, author, and tags, while also having specific attributes like image dimensions for images or video duration for videos.
|
||||||
etc. Each type of content could have shared attributes like creation date, author, and tags, while also having
|
|
||||||
specific attributes like image dimensions for images or video duration for videos.
|
|
||||||
|
|
||||||
* File Systems: If you're designing a file system where different types of files need to be managed, such as documents,
|
* File Systems: If you're designing a file system where different types of files need to be managed, such as documents, images, audio files, and directories, the Abstract Document pattern can help provide a consistent way to access attributes like file size, creation date, etc., while allowing for specific attributes like image resolution or audio duration.
|
||||||
images, audio files, and directories, the Abstract Document pattern can help provide a consistent way to access
|
|
||||||
attributes like file size, creation date, etc., while allowing for specific attributes like image resolution or audio
|
|
||||||
duration.
|
|
||||||
|
|
||||||
* E-commerce Systems: An e-commerce platform might have different product types such as physical products, digital
|
* E-commerce Systems: An e-commerce platform might have different product types such as physical products, digital downloads, and subscriptions. Each type could share common attributes like name, price, and description, while having unique attributes like shipping weight for physical products or download link for digital products.
|
||||||
downloads, and subscriptions. Each type could share common attributes like name, price, and description, while having
|
|
||||||
unique attributes like shipping weight for physical products or download link for digital products.
|
|
||||||
|
|
||||||
* Medical Records Systems: In healthcare, patient records might include various types of data such as demographics,
|
* Medical Records Systems: In healthcare, patient records might include various types of data such as demographics, medical history, test results, and prescriptions. The Abstract Document pattern can help manage shared attributes like patient ID and date of birth, while accommodating specialized attributes like test results or prescribed medications.
|
||||||
medical history, test results, and prescriptions. The Abstract Document pattern can help manage shared attributes like
|
|
||||||
patient ID and date of birth, while accommodating specialized attributes like test results or prescribed medications.
|
|
||||||
|
|
||||||
* Configuration Management: When dealing with configuration settings for software applications, there can be different
|
* Configuration Management: When dealing with configuration settings for software applications, there can be different types of configuration elements, each with its own set of attributes. The Abstract Document pattern can be used to manage these configuration elements while ensuring a consistent way to access and manipulate their attributes.
|
||||||
types of configuration elements, each with its own set of attributes. The Abstract Document pattern can be used to
|
|
||||||
manage these configuration elements while ensuring a consistent way to access and manipulate their attributes.
|
|
||||||
|
|
||||||
* Educational Platforms: Educational systems might have various types of learning materials such as text-based content,
|
* Educational Platforms: Educational systems might have various types of learning materials such as text-based content, videos, quizzes, and assignments. Common attributes like title, author, and publication date can be shared, while unique attributes like video duration or assignment due dates can be specific to each type.
|
||||||
videos, quizzes, and assignments. Common attributes like title, author, and publication date can be shared, while
|
|
||||||
unique attributes like video duration or assignment due dates can be specific to each type.
|
|
||||||
|
|
||||||
* Project Management Tools: In project management applications, you could have different types of tasks like to-do
|
* Project Management Tools: In project management applications, you could have different types of tasks like to-do items, milestones, and issues. The Abstract Document pattern could be used to handle general attributes like task name and assignee, while allowing for specific attributes like milestone date or issue priority.
|
||||||
items, milestones, and issues. The Abstract Document pattern could be used to handle general attributes like task name
|
|
||||||
and assignee, while allowing for specific attributes like milestone date or issue priority.
|
|
||||||
|
|
||||||
* Documents have diverse and evolving attribute structures.
|
* Documents have diverse and evolving attribute structures.
|
||||||
|
|
||||||
@@ -221,10 +195,7 @@ scenarios where the Abstract Document design pattern can be applicable:
|
|||||||
|
|
||||||
* Maintainability and flexibility are critical for the codebase.
|
* Maintainability and flexibility are critical for the codebase.
|
||||||
|
|
||||||
The key idea behind the Abstract Document design pattern is to provide a flexible and extensible way to manage different
|
The key idea behind the Abstract Document design pattern is to provide a flexible and extensible way to manage different types of documents or entities with shared and distinct attributes. By defining a common interface and implementing it across various document types, you can achieve a more organized and consistent approach to handling complex data structures.
|
||||||
types of documents or entities with shared and distinct attributes. By defining a common interface and implementing it
|
|
||||||
across various document types, you can achieve a more organized and consistent approach to handling complex data
|
|
||||||
structures.
|
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
|
|||||||
+11
-24
@@ -14,32 +14,25 @@ Kit
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Abstract Factory design pattern provides a way to create families of related objects without specifying their
|
The Abstract Factory design pattern provides a way to create families of related objects without specifying their concrete classes. This allows for code that is independent of the specific classes of objects it uses, promoting flexibility and maintainability.
|
||||||
concrete classes. This allows for code that is independent of the specific classes of objects it uses, promoting
|
|
||||||
flexibility and maintainability.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real-world example
|
Real-world example
|
||||||
|
|
||||||
> To create a kingdom we need objects with a common theme. The elven kingdom needs an elven king, elven castle, and
|
> To create a kingdom we need objects with a common theme. The elven kingdom needs an elven king, elven castle, and elven army whereas the orcish kingdom needs an orcish king, orcish castle, and orcish army. There is a dependency between the objects in the kingdom.
|
||||||
> elven army whereas the orcish kingdom needs an orcish king, orcish castle, and orcish army. There is a dependency
|
|
||||||
> between the objects in the kingdom.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> A factory of factories; a factory that groups the individual but related/dependent factories together without
|
> A factory of factories; a factory that groups the individual but related/dependent factories together without specifying their concrete classes.
|
||||||
> specifying their concrete classes.
|
|
||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme
|
> The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes
|
||||||
> without specifying their concrete classes
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
Translating the kingdom example above. First of all, we have some interfaces and implementation for the objects in the
|
Translating the kingdom example above. First of all, we have some interfaces and implementation for the objects in the kingdom.
|
||||||
kingdom.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public interface Castle {
|
public interface Castle {
|
||||||
@@ -134,8 +127,7 @@ public class OrcKingdomFactory implements KingdomFactory {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now we have the abstract factory that lets us make a family of related objects i.e. elven kingdom factory creates elven
|
Now we have the abstract factory that lets us make a family of related objects i.e. elven kingdom factory creates elven castle, king and army, etc.
|
||||||
castle, king and army, etc.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
var factory=new ElfKingdomFactory();
|
var factory=new ElfKingdomFactory();
|
||||||
@@ -156,11 +148,7 @@ This is the elven castle!
|
|||||||
This is the elven Army!
|
This is the elven Army!
|
||||||
```
|
```
|
||||||
|
|
||||||
Now, we can design a factory for our different kingdom factories. In this example, we created `FactoryMaker`,
|
Now, we can design a factory for our different kingdom factories. In this example, we created `FactoryMaker`, responsible for returning an instance of either `ElfKingdomFactory` or `OrcKingdomFactory`. The client can use `FactoryMaker` to create the desired concrete factory which, in turn, will produce different concrete objects (derived from `Army`, `King`, `Castle`). In this example, we also used an enum to parameterize which type of kingdom factory the client will ask for.
|
||||||
responsible for returning an instance of either `ElfKingdomFactory` or `OrcKingdomFactory`. The client can
|
|
||||||
use `FactoryMaker` to create the desired concrete factory which, in turn, will produce different concrete objects (
|
|
||||||
derived from `Army`, `King`, `Castle`). In this example, we also used an enum to parameterize which type of kingdom
|
|
||||||
factory the client will ask for.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public static class FactoryMaker {
|
public static class FactoryMaker {
|
||||||
@@ -203,8 +191,7 @@ Use the Abstract Factory pattern when
|
|||||||
* The system should be independent of how its products are created, composed, and represented
|
* The system should be independent of how its products are created, composed, and represented
|
||||||
* The system should be configured with one of the multiple families of products
|
* The system should be configured with one of the multiple families of products
|
||||||
* The family of related product objects is designed to be used together, and you need to enforce this constraint
|
* The family of related product objects is designed to be used together, and you need to enforce this constraint
|
||||||
* You want to provide a class library of products, and you want to reveal just their interfaces, not their
|
* You want to provide a class library of products, and you want to reveal just their interfaces, not their implementations
|
||||||
implementations
|
|
||||||
* The lifetime of the dependency is conceptually shorter than the lifetime of the consumer.
|
* The lifetime of the dependency is conceptually shorter than the lifetime of the consumer.
|
||||||
* You need a run-time value to construct a particular dependency
|
* You need a run-time value to construct a particular dependency
|
||||||
* You want to decide which product to call from a family at runtime.
|
* You want to decide which product to call from a family at runtime.
|
||||||
@@ -214,8 +201,7 @@ Use the Abstract Factory pattern when
|
|||||||
|
|
||||||
Example use cases
|
Example use cases
|
||||||
|
|
||||||
* Selecting to call to the appropriate implementation of FileSystemAcmeService or DatabaseAcmeService or
|
* Selecting to call to the appropriate implementation of FileSystemAcmeService or DatabaseAcmeService or NetworkAcmeService at runtime.
|
||||||
NetworkAcmeService at runtime.
|
|
||||||
* Unit test case writing becomes much easier
|
* Unit test case writing becomes much easier
|
||||||
* UI tools for different OS
|
* UI tools for different OS
|
||||||
|
|
||||||
@@ -258,4 +244,5 @@ Trade-offs
|
|||||||
* [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)
|
* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)
|
||||||
* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)
|
* [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)
|
||||||
* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3HWNf4U)
|
* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3HWNf4U)
|
||||||
* [Design Patterns in Java](https://amzn.to/3Syw0vC)
|
* [Design Patterns in Java](https://amzn.to/3Syw0vC)
|
||||||
|
*
|
||||||
+6
-13
@@ -8,22 +8,17 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Active Object design pattern provides a safe and reliable way to implement asynchronous behavior in concurrent
|
The Active Object design pattern provides a safe and reliable way to implement asynchronous behavior in concurrent systems. It achieves this by encapsulating tasks within objects that have their own thread and message queue. This separation keeps the main thread responsive and avoids issues like direct thread manipulation or shared state access.
|
||||||
systems. It achieves this by encapsulating tasks within objects that have their own thread and message queue. This
|
|
||||||
separation keeps the main thread responsive and avoids issues like direct thread manipulation or shared state access.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
The class that implements the active object pattern will contain a self-synchronization mechanism without using '
|
The class that implements the active object pattern will contain a self-synchronization mechanism without using 'synchronized' methods.
|
||||||
synchronized' methods.
|
|
||||||
|
|
||||||
Real-world example
|
Real-world example
|
||||||
|
|
||||||
> The Orcs are known for their wildness and untameable soul. It seems like they have their own thread of control based
|
> The Orcs are known for their wildness and untameable soul. It seems like they have their own thread of control based on previous behavior.
|
||||||
> on previous behavior.
|
|
||||||
|
|
||||||
To implement a creature that has its own thread of control mechanism and expose its API only and not the execution
|
To implement a creature that has its own thread of control mechanism and expose its API only and not the execution itself, we can use the Active Object pattern.
|
||||||
itself, we can use the Active Object pattern.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
@@ -83,8 +78,7 @@ public abstract class ActiveCreature {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
We can see that any class that will extend the ActiveCreature class will have its own thread of control to invoke and
|
We can see that any class that will extend the ActiveCreature class will have its own thread of control to invoke and execute methods.
|
||||||
execute methods.
|
|
||||||
|
|
||||||
For example, the Orc class:
|
For example, the Orc class:
|
||||||
|
|
||||||
@@ -98,8 +92,7 @@ public class Orc extends ActiveCreature {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now, we can create multiple creatures such as Orcs, tell them to eat and roam, and they will execute it on their own
|
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:
|
||||||
thread of control:
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public static void main(String[]args){
|
public static void main(String[]args){
|
||||||
|
|||||||
@@ -9,15 +9,13 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Acyclic Visitor pattern decouples operations from an object hierarchy, allowing you to add new operations without
|
The Acyclic Visitor pattern decouples operations from an object hierarchy, allowing you to add new operations without modifying the object structure directly.
|
||||||
modifying the object structure directly.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> We have a hierarchy of modem classes. The modems in this hierarchy need to be visited by an external algorithm based
|
> We have a hierarchy of modem classes. The modems in this hierarchy need to be visited by an external algorithm based on filtering criteria (is it Unix or DOS compatible modem).
|
||||||
> on filtering criteria (is it Unix or DOS compatible modem).
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
@@ -25,8 +23,7 @@ In plain words
|
|||||||
|
|
||||||
[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) says
|
[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) says
|
||||||
|
|
||||||
> The Acyclic Visitor pattern allows new functions to be added to existing class hierarchies without affecting those
|
> The Acyclic Visitor pattern allows new functions to be added to existing class hierarchies without affecting those hierarchies, and without creating the dependency cycles that are inherent to the GangOfFour VisitorPattern.
|
||||||
> hierarchies, and without creating the dependency cycles that are inherent to the GangOfFour VisitorPattern.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
@@ -136,8 +133,7 @@ Program output:
|
|||||||
This pattern can be used:
|
This pattern can be used:
|
||||||
|
|
||||||
* When you need to add a new function to an existing hierarchy without the need to alter or affect that hierarchy.
|
* When you need to add a new function to an existing hierarchy without the need to alter or affect that hierarchy.
|
||||||
* When there are functions that operate upon a hierarchy, but which do not belong in the hierarchy itself. e.g. the
|
* When there are functions that operate upon a hierarchy, but which do not belong in the hierarchy itself. e.g. the ConfigureForDOS / ConfigureForUnix / ConfigureForX issue.
|
||||||
ConfigureForDOS / ConfigureForUnix / ConfigureForX issue.
|
|
||||||
* When you need to perform very different operations on an object depending upon its type.
|
* When you need to perform very different operations on an object depending upon its type.
|
||||||
* When the visited class hierarchy will be frequently extended with new derivatives of the Element class.
|
* When the visited class hierarchy will be frequently extended with new derivatives of the Element class.
|
||||||
* When the recompilation, relinking, retesting or redistribution of the derivatives of Element is very expensive.
|
* When the recompilation, relinking, retesting or redistribution of the derivatives of Element is very expensive.
|
||||||
@@ -156,8 +152,7 @@ Benefits:
|
|||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* Violates [Liskov's Substitution Principle](https://java-design-patterns.com/principles/#liskov-substitution-principle)
|
* Violates [Liskov's Substitution Principle](https://java-design-patterns.com/principles/#liskov-substitution-principle) by showing that it can accept all visitors but actually only being interested in particular visitors.
|
||||||
by showing that it can accept all visitors but actually only being interested in particular visitors.
|
|
||||||
* Parallel hierarchy of visitors has to be created for all members in visitable class hierarchy.
|
* Parallel hierarchy of visitors has to be created for all members in visitable class hierarchy.
|
||||||
|
|
||||||
## Related patterns
|
## Related patterns
|
||||||
|
|||||||
+10
-26
@@ -14,19 +14,13 @@ Wrapper
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Adapter pattern converts the interface of a class into another interface that clients expect, enabling
|
The Adapter pattern converts the interface of a class into another interface that clients expect, enabling compatibility.
|
||||||
compatibility.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real-world example
|
Real-world example
|
||||||
|
|
||||||
> Consider that you have some pictures on your memory card and you need to transfer them to your computer. To transfer
|
> Consider that you have some pictures on your memory card and you need to transfer them to your computer. To transfer them, you need some kind of adapter that is compatible with your computer ports so that you can attach a memory card to your computer. In this case card reader is an adapter. Another example would be the famous power adapter; a three-legged plug can't be connected to a two-pronged outlet, it needs to use a power adapter that makes it compatible with the two-pronged outlets. Yet another example would be a translator translating words spoken by one person to another
|
||||||
> them, you need some kind of adapter that is compatible with your computer ports so that you can attach a memory card
|
|
||||||
> to your computer. In this case card reader is an adapter. Another example would be the famous power adapter; a
|
|
||||||
> three-legged plug can't be connected to a two-pronged outlet, it needs to use a power adapter that makes it compatible
|
|
||||||
> with the two-pronged outlets. Yet another example would be a translator translating words spoken by one person to
|
|
||||||
> another
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
@@ -34,9 +28,7 @@ In plain words
|
|||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing
|
> In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code.
|
||||||
> class to be used as another interface. It is often used to make existing classes work with others without modifying
|
|
||||||
> their source code.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
@@ -75,8 +67,7 @@ public class Captain {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now let's say the pirates are coming and our captain needs to escape but there is only a fishing boat available. We need
|
Now let's say the pirates are coming and our captain needs to escape but there is only a fishing boat available. We need to create an adapter that allows the captain to operate the fishing boat with his rowing boat skills.
|
||||||
to create an adapter that allows the captain to operate the fishing boat with his rowing boat skills.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@@ -112,13 +103,9 @@ var captain=new Captain(new FishingBoatAdapter());
|
|||||||
Use the Adapter pattern when
|
Use the Adapter pattern when
|
||||||
|
|
||||||
* You want to use an existing class, and its interface does not match the one you need
|
* You want to use an existing class, and its interface does not match the one you need
|
||||||
* You want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don't
|
* You want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don't necessarily have compatible interfaces
|
||||||
necessarily have compatible interfaces
|
* You need to use several existing subclasses, but it's impractical to adapt their interface by subclassing everyone. An object adapter can adapt the interface of its parent class.
|
||||||
* You need to use several existing subclasses, but it's impractical to adapt their interface by subclassing everyone. An
|
* Most of the applications using third-party libraries use adapters as a middle layer between the application and the 3rd party library to decouple the application from the library. If another library has to be used only an adapter for the new library is required without having to change the application code.
|
||||||
object adapter can adapt the interface of its parent class.
|
|
||||||
* Most of the applications using third-party libraries use adapters as a middle layer between the application and the
|
|
||||||
3rd party library to decouple the application from the library. If another library has to be used only an adapter for
|
|
||||||
the new library is required without having to change the application code.
|
|
||||||
|
|
||||||
## Tutorials
|
## Tutorials
|
||||||
|
|
||||||
@@ -131,17 +118,14 @@ Use the Adapter pattern when
|
|||||||
|
|
||||||
Class and object adapters have different trade-offs. A class adapter
|
Class and object adapters have different trade-offs. A class adapter
|
||||||
|
|
||||||
* Adapts Adaptee to Target by committing to a concrete Adaptee class. As a consequence, a class adapter won’t work when
|
* Adapts Adaptee to Target by committing to a concrete Adaptee class. As a consequence, a class adapter won’t work when we want to adapt a class and all its subclasses.
|
||||||
we want to adapt a class and all its subclasses.
|
|
||||||
* Lets Adapter override some of Adaptee’s behavior since Adapter is a subclass of Adaptee.
|
* Lets Adapter override some of Adaptee’s behavior since Adapter is a subclass of Adaptee.
|
||||||
* Introduces only one object, and no additional pointer indirection is needed to get to the adaptee.
|
* Introduces only one object, and no additional pointer indirection is needed to get to the adaptee.
|
||||||
|
|
||||||
An object adapter
|
An object adapter
|
||||||
|
|
||||||
* Lets a single Adapter work with many Adaptees, that is, the Adaptee itself and all of its subclasses (if any). The
|
* Lets a single Adapter work with many Adaptees, that is, the Adaptee itself and all of its subclasses (if any). The Adapter can also add functionality to all Adaptees at once.
|
||||||
Adapter can also add functionality to all Adaptees at once.
|
* Makes it harder to override Adaptee behavior. It will require subclassing Adaptee and making the Adapter refer to the subclass rather than the Adaptee itself.
|
||||||
* Makes it harder to override Adaptee behavior. It will require subclassing Adaptee and making the Adapter refer to the
|
|
||||||
subclass rather than the Adaptee itself.
|
|
||||||
|
|
||||||
## Real-world examples
|
## Real-world examples
|
||||||
|
|
||||||
|
|||||||
@@ -11,17 +11,13 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
Streamline client's interactions with system's microservices by providing a single aggregation point that consolidates
|
Streamline client's interactions with system's microservices by providing a single aggregation point that consolidates data and responses from multiple services. This simplifies the client's communication with the system, improving efficiency and reducing complexity.
|
||||||
data and responses from multiple services. This simplifies the client's communication with the system, improving
|
|
||||||
efficiency and reducing complexity.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> Our web marketplace needs information about products and their current inventory. It makes a call to an aggregator
|
> Our web marketplace needs information about products and their current inventory. It makes a call to an aggregator service, which, in turn, calls the product information and product inventory microservices, returning the combined information.
|
||||||
> service, which, in turn, calls the product information and product inventory microservices, returning the combined
|
|
||||||
> information.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
@@ -44,8 +40,7 @@ public class Product {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Next we can introduce our `Aggregator` microservice. It contains clients `ProductInformationClient` and
|
Next we can introduce our `Aggregator` microservice. It contains clients `ProductInformationClient` and `ProductInventoryClient` for calling respective microservices.
|
||||||
`ProductInventoryClient` for calling respective microservices.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@@ -76,8 +71,7 @@ public class Aggregator {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Here's the essence of information microservice implementation. Inventory microservice is similar, it just returns
|
Here's the essence of information microservice implementation. Inventory microservice is similar, it just returns inventory counts.
|
||||||
inventory counts.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@@ -103,41 +97,27 @@ curl http://localhost:50004/product
|
|||||||
|
|
||||||
## Applicability
|
## Applicability
|
||||||
|
|
||||||
The Aggregator Microservices Design Pattern is particularly useful in scenarios where a client requires a composite
|
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.
|
||||||
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.
|
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* Simplified Client: Clients interact with just one service rather than managing calls to multiple microservices, which
|
* Simplified Client: Clients interact with just one service rather than managing calls to multiple microservices, which simplifies client-side logic.
|
||||||
simplifies client-side logic.
|
* Reduced Latency: By aggregating responses, the number of network calls is reduced, which can improve the application's overall latency.
|
||||||
* Reduced Latency: By aggregating responses, the number of network calls is reduced, which can improve the application's
|
* Decoupling: Clients are decoupled from the individual microservices, allowing for more flexibility in changing the microservices landscape without impacting clients.
|
||||||
overall latency.
|
* Centralized Logic: Aggregation allows for centralized transformation and logic application on the data collected from various services, which can be more efficient than handling it in the client or spreading it across multiple services.
|
||||||
* Decoupling: Clients are decoupled from the individual microservices, allowing for more flexibility in changing the
|
|
||||||
microservices landscape without impacting clients.
|
|
||||||
* Centralized Logic: Aggregation allows for centralized transformation and logic application on the data collected from
|
|
||||||
various services, which can be more efficient than handling it in the client or spreading it across multiple services.
|
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* Single Point of Failure: The aggregator service can become a bottleneck or a single point of failure if not designed
|
* Single Point of Failure: The aggregator service can become a bottleneck or a single point of failure if not designed with high availability and scalability in mind.
|
||||||
with high availability and scalability in mind.
|
* Complexity: Implementing an aggregator can introduce complexity, especially in terms of data aggregation logic and error handling when dealing with multiple services.
|
||||||
* Complexity: Implementing an aggregator can introduce complexity, especially in terms of data aggregation logic and
|
|
||||||
error handling when dealing with multiple services.
|
|
||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
* [API Gateway](https://java-design-patterns.com/patterns/api-gateway/): The Aggregator Microservices pattern is often
|
* [API Gateway](https://java-design-patterns.com/patterns/api-gateway/): The Aggregator Microservices pattern is often used in conjunction with an API Gateway, which provides a single entry point for clients to access multiple microservices.
|
||||||
used in conjunction with an API Gateway, which provides a single entry point for clients to access multiple
|
* [Composite](https://java-design-patterns.com/patterns/composite/): The Aggregator Microservices pattern can be seen as a form of the Composite pattern, where the composite is the aggregated response from multiple microservices.
|
||||||
microservices.
|
* [Facade](https://java-design-patterns.com/patterns/facade/): The Aggregator Microservices pattern can be seen as a form of the Facade pattern, where the facade is the aggregator service that provides a simplified interface to the client.
|
||||||
* [Composite](https://java-design-patterns.com/patterns/composite/): The Aggregator Microservices pattern can be seen as
|
|
||||||
a form of the Composite pattern, where the composite is the aggregated response from multiple microservices.
|
|
||||||
* [Facade](https://java-design-patterns.com/patterns/facade/): The Aggregator Microservices pattern can be seen as a
|
|
||||||
form of the Facade pattern, where the facade is the aggregator service that provides a simplified interface to the
|
|
||||||
client.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+21
-54
@@ -19,27 +19,19 @@ Provide a helper service instance on a client and offload common functionality a
|
|||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> A remote service has many clients accessing a function it provides. The service is a legacy application and is
|
> A remote service has many clients accessing a function it provides. The service is a legacy application and is impossible to update. Large numbers of requests from users are causing connectivity issues. New rules for request frequency should be implemented along with latency checks and client-side logging.
|
||||||
> impossible to update. Large numbers of requests from users are causing connectivity issues. New rules for request
|
|
||||||
> frequency should be implemented along with latency checks and client-side logging.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> With the Ambassador pattern, we can implement less-frequent polling from clients along with latency checks and
|
> With the Ambassador pattern, we can implement less-frequent polling from clients along with latency checks and logging.
|
||||||
> logging.
|
|
||||||
|
|
||||||
Microsoft documentation states
|
Microsoft documentation states
|
||||||
|
|
||||||
> An ambassador service can be thought of as an out-of-process proxy which is co-located with the client. This pattern
|
> An ambassador service can be thought of as an out-of-process proxy which is co-located with the client. This pattern can be useful for offloading common client connectivity tasks such as monitoring, logging, routing, security (such as TLS), and resiliency patterns in a language agnostic way. It is often used with legacy applications, or other applications that are difficult to modify, in order to extend their networking capabilities. It can also enable a specialized team to implement those features.
|
||||||
> can be useful for offloading common client connectivity tasks such as monitoring, logging, routing,
|
|
||||||
> security (such as TLS), and resiliency patterns in a language agnostic way. It is often used with legacy applications,
|
|
||||||
> or other applications that are difficult to modify, in order to extend their networking capabilities. It can also
|
|
||||||
> enable a specialized team to implement those features.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
With the above introduction in mind we will imitate the functionality in this example. We have an interface implemented
|
With the above introduction in mind we will imitate the functionality in this example. We have an interface implemented by the remote service as well as the ambassador service:
|
||||||
by the remote service as well as the ambassador service:
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
interface RemoteServiceInterface {
|
interface RemoteServiceInterface {
|
||||||
@@ -181,10 +173,8 @@ Time taken(ms):111
|
|||||||
|
|
||||||
## Applicability
|
## Applicability
|
||||||
|
|
||||||
* Cloud Native and Microservices Architectures: Especially useful in distributed systems where it's crucial to monitor,
|
* Cloud Native and Microservices Architectures: Especially useful in distributed systems where it's crucial to monitor, log, and secure inter-service communication.
|
||||||
log, and secure inter-service communication.
|
* Legacy System Integration: Facilitates communication with newer services by handling necessary but non-core functionalities.
|
||||||
* Legacy System Integration: Facilitates communication with newer services by handling necessary but non-core
|
|
||||||
functionalities.
|
|
||||||
* Performance Enhancement: Can be used to cache results or compress data to improve communication efficiency.
|
* Performance Enhancement: Can be used to cache results or compress data to improve communication efficiency.
|
||||||
|
|
||||||
Typical use cases include:
|
Typical use cases include:
|
||||||
@@ -199,57 +189,34 @@ Typical use cases include:
|
|||||||
|
|
||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* Separation of Concerns: Offloads cross-cutting concerns from the service logic, leading to cleaner, more maintainable
|
* Separation of Concerns: Offloads cross-cutting concerns from the service logic, leading to cleaner, more maintainable code.
|
||||||
code.
|
* Reusable Infrastructure Logic: The ambassador pattern allows the same logic (e.g., logging, monitoring) to be reused across multiple services.
|
||||||
* Reusable Infrastructure Logic: The ambassador pattern allows the same logic (e.g., logging, monitoring) to be reused
|
* Improved Security: Centralizes security features like SSL termination or authentication, reducing the risk of misconfiguration.
|
||||||
across multiple services.
|
|
||||||
* Improved Security: Centralizes security features like SSL termination or authentication, reducing the risk of
|
|
||||||
misconfiguration.
|
|
||||||
* Flexibility: Makes it easier to update or replace infrastructure concerns without modifying the service code.
|
* Flexibility: Makes it easier to update or replace infrastructure concerns without modifying the service code.
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* Increased Complexity: Adds another layer to the architecture, which can complicate the system design and debugging.
|
* Increased Complexity: Adds another layer to the architecture, which can complicate the system design and debugging.
|
||||||
* Potential Performance Overhead: The additional network hop can introduce latency and overhead, particularly if not
|
* Potential Performance Overhead: The additional network hop can introduce latency and overhead, particularly if not optimized.
|
||||||
optimized.
|
|
||||||
* Deployment Overhead: Requires additional resources and management for deploying and scaling ambassador services.
|
* Deployment Overhead: Requires additional resources and management for deploying and scaling ambassador services.
|
||||||
|
|
||||||
## Known uses
|
## Known uses
|
||||||
|
|
||||||
* Service Mesh Implementations: In a service mesh architecture, like Istio or Linkerd, the Ambassador pattern is often
|
* Service Mesh Implementations: In a service mesh architecture, like Istio or Linkerd, the Ambassador pattern is often employed as a sidecar proxy that handles inter-service communications. This includes tasks such as service discovery, routing, load balancing, telemetry (metrics and tracing), and security (authentication and authorization).
|
||||||
employed as a sidecar proxy that handles inter-service communications. This includes tasks such as service discovery,
|
* API Gateways: API gateways can use the Ambassador pattern to encapsulate common functionalities like rate limiting, caching, request shaping, and authentication. This allows backend services to focus on their core business logic without being burdened by these cross-cutting concerns.
|
||||||
routing, load balancing, telemetry (metrics and tracing), and security (authentication and authorization).
|
* Logging and Monitoring: An Ambassador can aggregate logs and metrics from various services and forward them to centralized monitoring tools like Prometheus or ELK Stack (Elasticsearch, Logstash, Kibana). This simplifies the logging and monitoring setup for each service and provides a unified view of the system's health.
|
||||||
* API Gateways: API gateways can use the Ambassador pattern to encapsulate common functionalities like rate limiting,
|
* Security: Security-related functionalities such as SSL/TLS termination, identity verification, and encryption can be managed by an Ambassador. This ensures consistent security practices across services and reduces the likelihood of security breaches due to misconfigurations.
|
||||||
caching, request shaping, and authentication. This allows backend services to focus on their core business logic
|
* Resilience: The Ambassador can implement resilience patterns like circuit breakers, retries, and timeouts. For instance, Netflix's Hystrix library can be used within an Ambassador to prevent cascading failures in a microservices ecosystem.
|
||||||
without being burdened by these cross-cutting concerns.
|
* Database Proxy: Ambassadors can act as proxies for database connections, providing functionalities like connection pooling, read/write splitting for replicas, and query caching. This offloads significant complexity from the application services.
|
||||||
* Logging and Monitoring: An Ambassador can aggregate logs and metrics from various services and forward them to
|
* Legacy System Integration: In scenarios where modern microservices need to communicate with legacy systems, an Ambassador can serve as an intermediary that translates protocols, handles necessary transformations, and implements modern security practices, easing the integration process.
|
||||||
centralized monitoring tools like Prometheus or ELK Stack (Elasticsearch, Logstash, Kibana). This simplifies the
|
* Network Optimization: For services deployed across different geographical locations or cloud regions, Ambassadors can optimize communication by compressing data, batching requests, or even implementing smart routing to reduce latency and costs.
|
||||||
logging and monitoring setup for each service and provides a unified view of the system's health.
|
|
||||||
* Security: Security-related functionalities such as SSL/TLS termination, identity verification, and encryption can be
|
|
||||||
managed by an Ambassador. This ensures consistent security practices across services and reduces the likelihood of
|
|
||||||
security breaches due to misconfigurations.
|
|
||||||
* Resilience: The Ambassador can implement resilience patterns like circuit breakers, retries, and timeouts. For
|
|
||||||
instance, Netflix's Hystrix library can be used within an Ambassador to prevent cascading failures in a microservices
|
|
||||||
ecosystem.
|
|
||||||
* Database Proxy: Ambassadors can act as proxies for database connections, providing functionalities like connection
|
|
||||||
pooling, read/write splitting for replicas, and query caching. This offloads significant complexity from the
|
|
||||||
application services.
|
|
||||||
* Legacy System Integration: In scenarios where modern microservices need to communicate with legacy systems, an
|
|
||||||
Ambassador can serve as an intermediary that translates protocols, handles necessary transformations, and implements
|
|
||||||
modern security practices, easing the integration process.
|
|
||||||
* Network Optimization: For services deployed across different geographical locations or cloud regions, Ambassadors can
|
|
||||||
optimize communication by compressing data, batching requests, or even implementing smart routing to reduce latency
|
|
||||||
and costs.
|
|
||||||
* [Kubernetes-native API gateway for microservices](https://github.com/datawire/ambassador)
|
* [Kubernetes-native API gateway for microservices](https://github.com/datawire/ambassador)
|
||||||
|
|
||||||
## Related patterns
|
## Related patterns
|
||||||
|
|
||||||
* [Proxy](https://java-design-patterns.com/patterns/proxy/): Shares similarities with the proxy pattern, but the
|
* [Proxy](https://java-design-patterns.com/patterns/proxy/): Shares similarities with the proxy pattern, but the ambassador pattern specifically focuses on offloading ancillary functionalities.
|
||||||
ambassador pattern specifically focuses on offloading ancillary functionalities.
|
* Sidecar: A similar pattern used in the context of containerized applications, where a sidecar container provides additional functionality to the main application container.
|
||||||
* Sidecar: A similar pattern used in the context of containerized applications, where a sidecar container provides
|
* [Decorator](https://java-design-patterns.com/patterns/decorator/): The decorator pattern is used to add functionality to an object dynamically, while the ambassador pattern is used to offload functionality to a separate object.
|
||||||
additional functionality to the main application container.
|
|
||||||
* [Decorator](https://java-design-patterns.com/patterns/decorator/): The decorator pattern is used to add functionality
|
|
||||||
to an object dynamically, while the ambassador pattern is used to offload functionality to a separate object.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
@@ -16,34 +16,21 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
Implement a façade or adapter layer between different subsystems that don't share the same semantics. It translates
|
Implement a façade or adapter layer between different subsystems that don't share the same semantics. It translates between different data formats and systems, ensuring that the integration between systems does not lead to corruption of business logic or data integrity.
|
||||||
between different data formats and systems, ensuring that the integration between systems does not lead to corruption of
|
|
||||||
business logic or data integrity.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
### Context and problem
|
### Context and problem
|
||||||
|
|
||||||
Most applications rely on other systems for some data or functionality. For example, when a legacy application is
|
Most applications rely on other systems for some data or functionality. For example, when a legacy application is migrated to a modern system, it may still need existing legacy resources. New features must be able to call the legacy system. This is especially true of gradual migrations, where different features of a larger application are moved to a modern system over time.
|
||||||
migrated to a modern system, it may still need existing legacy resources. New features must be able to call the legacy
|
|
||||||
system. This is especially true of gradual migrations, where different features of a larger application are moved to a
|
|
||||||
modern system over time.
|
|
||||||
|
|
||||||
Often these legacy systems suffer from quality issues such as convoluted data schemas or obsolete APIs. The features and
|
Often these legacy systems suffer from quality issues such as convoluted data schemas or obsolete APIs. The features and technologies used in legacy systems can vary widely from more modern systems. To interoperate with the legacy system, the new application may need to support outdated infrastructure, protocols, data models, APIs, or other features that you wouldn't otherwise put into a modern application.
|
||||||
technologies used in legacy systems can vary widely from more modern systems. To interoperate with the legacy system,
|
|
||||||
the new application may need to support outdated infrastructure, protocols, data models, APIs, or other features that
|
|
||||||
you wouldn't otherwise put into a modern application.
|
|
||||||
|
|
||||||
Maintaining access between new and legacy systems can force the new system to adhere to at least some of the legacy
|
Maintaining access between new and legacy systems can force the new system to adhere to at least some of the legacy system's APIs or other semantics. When these legacy features have quality issues, supporting them "corrupts" what might otherwise be a cleanly designed modern application. Similar issues can arise with any external system that your development team doesn't control, not just legacy systems.
|
||||||
system's APIs or other semantics. When these legacy features have quality issues, supporting them "corrupts" what might
|
|
||||||
otherwise be a cleanly designed modern application. Similar issues can arise with any external system that your
|
|
||||||
development team doesn't control, not just legacy systems.
|
|
||||||
|
|
||||||
### Solution
|
### Solution
|
||||||
|
|
||||||
Isolate the different subsystems by placing an anti-corruption layer between them. This layer translates communications
|
Isolate the different subsystems by placing an anti-corruption layer between them. This layer translates communications between the two systems, allowing one system to remain unchanged while the other can avoid compromising its design and technological approach.
|
||||||
between the two systems, allowing one system to remain unchanged while the other can avoid compromising its design and
|
|
||||||
technological approach.
|
|
||||||
|
|
||||||
### Programmatic example
|
### Programmatic example
|
||||||
|
|
||||||
@@ -53,15 +40,9 @@ The example shows why the anti-corruption layer is needed.
|
|||||||
|
|
||||||
Here are 2 shop-ordering systems: `Legacy` and `Modern`.
|
Here are 2 shop-ordering systems: `Legacy` and `Modern`.
|
||||||
|
|
||||||
The aforementioned systems have different domain models and have to operate simultaneously. Since they work
|
The aforementioned systems have different domain models and have to operate simultaneously. Since they work independently the orders can come either from the `Legacy` or `Modern` system. Therefore, the system that receives the legacyOrder needs to check if the legacyOrder is valid and not present in the other system. Then it can place the legacyOrder in its own system.
|
||||||
independently the orders can come either from the `Legacy` or `Modern` system. Therefore, the system that receives the
|
|
||||||
legacyOrder needs to check if the legacyOrder is valid and not present in the other system. Then it can place the
|
|
||||||
legacyOrder in its own system.
|
|
||||||
|
|
||||||
But for that, the system needs to know the domain model of the other system and to avoid that, the anti-corruption
|
But for that, the system needs to know the domain model of the other system and to avoid that, the anti-corruption layer(ACL) is introduced. The ACL is a layer that translates the domain model of the `Legacy` system to the domain model of the `Modern` system and vice versa. Also, it hides all other operations with the other system, uncoupling the systems.
|
||||||
layer(ACL) is introduced. The ACL is a layer that translates the domain model of the `Legacy` system to the domain model
|
|
||||||
of the `Modern` system and vice versa. Also, it hides all other operations with the other system, uncoupling the
|
|
||||||
systems.
|
|
||||||
|
|
||||||
#### Domain model of the `Legacy` system
|
#### Domain model of the `Legacy` system
|
||||||
|
|
||||||
@@ -122,9 +103,7 @@ public class AntiCorruptionLayer {
|
|||||||
|
|
||||||
#### The connection
|
#### The connection
|
||||||
|
|
||||||
Wherever the `Legacy` or `Modern` system needs to communicate with the counterpart the ACL needs to be used to avoid
|
Wherever the `Legacy` or `Modern` system needs to communicate with the counterpart the ACL needs to be used to avoid corrupting the current domain model. The example below shows how the `Legacy` system places an order with a validation from the `Modern` system.
|
||||||
corrupting the current domain model. The example below shows how the `Legacy` system places an order with a validation
|
|
||||||
from the `Modern` system.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class LegacyShop {
|
public class LegacyShop {
|
||||||
@@ -150,14 +129,11 @@ public class LegacyShop {
|
|||||||
|
|
||||||
Use this pattern when:
|
Use this pattern when:
|
||||||
|
|
||||||
* A migration is planned to happen over multiple stages, but integration between new and legacy systems needs to be
|
* A migration is planned to happen over multiple stages, but integration between new and legacy systems needs to be maintained
|
||||||
maintained
|
|
||||||
* Two or more subsystems have different semantics, but still need to communicate
|
* Two or more subsystems have different semantics, but still need to communicate
|
||||||
* When integrating with legacy systems or external systems where direct integration might pollute the domain model of
|
* When integrating with legacy systems or external systems where direct integration might pollute the domain model of the new system
|
||||||
the new system
|
|
||||||
* In scenarios where different subsystems within a larger system use different data formats or structures
|
* In scenarios where different subsystems within a larger system use different data formats or structures
|
||||||
* When there is a need to ensure loose coupling between different subsystems or external services to facilitate easier
|
* When there is a need to ensure loose coupling between different subsystems or external services to facilitate easier maintenance and scalability
|
||||||
maintenance and scalability
|
|
||||||
|
|
||||||
## Tutorials
|
## Tutorials
|
||||||
|
|
||||||
@@ -166,11 +142,9 @@ Use this pattern when:
|
|||||||
|
|
||||||
## Known Uses
|
## Known Uses
|
||||||
|
|
||||||
* Microservices architectures where individual services must communicate without being tightly coupled to each other’s
|
* Microservices architectures where individual services must communicate without being tightly coupled to each other’s data schemas
|
||||||
data schemas
|
|
||||||
* Enterprise systems integration, especially when integrating modern systems with legacy systems
|
* Enterprise systems integration, especially when integrating modern systems with legacy systems
|
||||||
* In bounded contexts within Domain-Driven Design (DDD) to maintain the integrity of a domain model when interacting
|
* In bounded contexts within Domain-Driven Design (DDD) to maintain the integrity of a domain model when interacting with external systems or subsystems
|
||||||
with external systems or subsystems
|
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
@@ -188,12 +162,9 @@ Trade-offs:
|
|||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
* [Facade](https://java-design-patterns.com/patterns/facade/): The Anti-Corruption Layer can be seen as a specialized
|
* [Facade](https://java-design-patterns.com/patterns/facade/): The Anti-Corruption Layer can be seen as a specialized form of the Facade pattern that is used to isolate different subsystems
|
||||||
form of the Facade pattern that is used to isolate different subsystems
|
* [Adapter](https://java-design-patterns.com/patterns/adapter/): The Anti-Corruption Layer can be implemented using the Adapter pattern to translate between different data formats or structures
|
||||||
* [Adapter](https://java-design-patterns.com/patterns/adapter/): The Anti-Corruption Layer can be implemented using the
|
* [Gateway](https://java-design-patterns.com/patterns/gateway/): The Anti-Corruption Layer can be used as a Gateway to external systems to provide a unified interface
|
||||||
Adapter pattern to translate between different data formats or structures
|
|
||||||
* [Gateway](https://java-design-patterns.com/patterns/gateway/): The Anti-Corruption Layer can be used as a Gateway to
|
|
||||||
external systems to provide a unified interface
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+11
-40
@@ -11,9 +11,7 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The API Gateway design pattern aims to provide a unified interface to a set of microservices. It acts as a single entry
|
The API Gateway design pattern aims to provide a unified interface to a set of microservices. It acts as a single entry point for clients, routing requests to the appropriate microservices and aggregating results, thereby simplifying the client-side code.
|
||||||
point for clients, routing requests to the appropriate microservices and aggregating results, thereby simplifying the
|
|
||||||
client-side code.
|
|
||||||
|
|
||||||
## Also known as
|
## Also known as
|
||||||
|
|
||||||
@@ -21,48 +19,25 @@ client-side code.
|
|||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
With the Microservices pattern, a client may need data from multiple different microservices. If the
|
With the Microservices pattern, a client may need data from multiple different microservices. If the client called each microservice directly, that could contribute to longer load times, since the client would have to make a network request for each microservice called. Moreover, having the client call each microservice directly ties the client to that microservice - if the internal implementations of the microservices change (for example, if two microservices are combined sometime in the future) or if the location (host and port) of a microservice changes, then every client that makes use of those microservices must be updated.
|
||||||
client called each microservice directly, that could contribute to longer load times, since the
|
|
||||||
client would have to make a network request for each microservice called. Moreover, having the
|
|
||||||
client call each microservice directly ties the client to that microservice - if the internal
|
|
||||||
implementations of the microservices change (for example, if two microservices are combined sometime
|
|
||||||
in the future) or if the location (host and port) of a microservice changes, then every client that
|
|
||||||
makes use of those microservices must be updated.
|
|
||||||
|
|
||||||
The intent of the API Gateway pattern is to alleviate some of these issues. In the API Gateway
|
The intent of the API Gateway pattern is to alleviate some of these issues. In the API Gateway pattern, an additional entity (the API Gateway) is placed between the client and the microservices. The job of the API Gateway is to aggregate the calls to the microservices. Rather than the client calling each microservice individually, the client calls the API Gateway a single time. The API Gateway then calls each of the microservices that the client needs.
|
||||||
pattern, an additional entity (the API Gateway) is placed between the client and the microservices.
|
|
||||||
The job of the API Gateway is to aggregate the calls to the microservices. Rather than the client
|
|
||||||
calling each microservice individually, the client calls the API Gateway a single time. The API
|
|
||||||
Gateway then calls each of the microservices that the client needs.
|
|
||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> We are implementing microservices and API Gateway pattern for an e-commerce site. In this system
|
> We are implementing microservices and API Gateway pattern for an e-commerce site. In this system the API Gateway makes calls to the Image and Price microservices.
|
||||||
> the API Gateway makes calls to the Image and Price microservices.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> For a system implemented using microservices architecture, API Gateway is the single entry point
|
> For a system implemented using microservices architecture, API Gateway is the single entry point that aggregates the calls to the individual microservices.
|
||||||
> that aggregates the calls to the individual microservices.
|
|
||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> API Gateway is a server that acts as an API front-end, receives API requests, enforces throttling
|
> API Gateway is a server that acts as an API front-end, receives API requests, enforces throttling and security policies, passes requests to the back-end service and then passes the response back to the requester. A gateway often includes a transformation engine to orchestrate and modify the requests and responses on the fly. A gateway can also provide functionality such as collecting analytics data and providing caching. The gateway can provide functionality to support authentication, authorization, security, audit and regulatory compliance.
|
||||||
> and security policies, passes requests to the back-end service and then passes the response back
|
|
||||||
> to the requester. A gateway often includes a transformation engine to orchestrate and modify the
|
|
||||||
> requests and responses on the fly. A gateway can also provide functionality such as collecting
|
|
||||||
> analytics data and providing caching. The gateway can provide functionality to support
|
|
||||||
> authentication, authorization, security, audit and regulatory compliance.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
This implementation shows what the API Gateway pattern could look like for an e-commerce site. The
|
This implementation shows what the API Gateway pattern could look like for an e-commerce site. The`ApiGateway` makes calls to the Image and Price microservices using the `ImageClientImpl` and `PriceClientImpl` respectively. Customers viewing the site on a desktop device can see both price information and an image of a product, so the `ApiGateway` calls both of the microservices and aggregates the data in the `DesktopProduct` model. However, mobile users only see price information; they do not see a product image. For mobile users, the `ApiGateway` only retrieves price information, which it uses to populate the `MobileProduct`.
|
||||||
`ApiGateway` makes calls to the Image and Price microservices using the `ImageClientImpl` and
|
|
||||||
`PriceClientImpl` respectively. Customers viewing the site on a desktop device can see both price
|
|
||||||
information and an image of a product, so the `ApiGateway` calls both of the microservices and
|
|
||||||
aggregates the data in the `DesktopProduct` model. However, mobile users only see price information;
|
|
||||||
they do not see a product image. For mobile users, the `ApiGateway` only retrieves price
|
|
||||||
information, which it uses to populate the `MobileProduct`.
|
|
||||||
|
|
||||||
Here's the Image microservice implementation.
|
Here's the Image microservice implementation.
|
||||||
|
|
||||||
@@ -155,8 +130,7 @@ public class ApiGateway {
|
|||||||
|
|
||||||
## Applicability
|
## Applicability
|
||||||
|
|
||||||
* When building a microservices architecture, and there's a need to abstract the complexity of microservices from the
|
* When building a microservices architecture, and there's a need to abstract the complexity of microservices from the client.
|
||||||
client.
|
|
||||||
* When multiple microservices need to be consumed in a single request.
|
* When multiple microservices need to be consumed in a single request.
|
||||||
* For authentication, authorization, and security enforcement at a single point.
|
* For authentication, authorization, and security enforcement at a single point.
|
||||||
* To optimize communication between clients and services, especially in a cloud environment.
|
* To optimize communication between clients and services, especially in a cloud environment.
|
||||||
@@ -184,12 +158,9 @@ Trade-offs:
|
|||||||
|
|
||||||
## Related patterns
|
## Related patterns
|
||||||
|
|
||||||
* [Aggregator Microservice](../aggregator-microservices/README.md) - The API Gateway pattern is often used in
|
* [Aggregator Microservice](../aggregator-microservices/README.md) - The API Gateway pattern is often used in conjunction with the Aggregator Microservice pattern to provide a unified interface to a set of microservices.
|
||||||
conjunction with the Aggregator Microservice pattern to provide a unified interface to a set of microservices.
|
* [Proxy](../proxy/README.md) - The API Gateway pattern is a specialized form of the Proxy pattern, where the gateway acts as a single entry point for clients, routing requests to the appropriate microservices and aggregating results.
|
||||||
* [Proxy](../proxy/README.md) - The API Gateway pattern is a specialized form of the Proxy pattern, where the gateway
|
* [Circuit Breaker](../circuit-breaker/README.md) - API Gateways can use the Circuit Breaker pattern to prevent cascading failures when calling multiple microservices.
|
||||||
acts as a single entry point for clients, routing requests to the appropriate microservices and aggregating results.
|
|
||||||
* [Circuit Breaker](../circuit-breaker/README.md) - API Gateways can use the Circuit Breaker pattern to prevent
|
|
||||||
cascading failures when calling multiple microservices.
|
|
||||||
|
|
||||||
## Tutorials
|
## Tutorials
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ Given/When/Then
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
Arrange/Act/Assert (AAA) is a pattern for organizing unit tests.
|
Arrange/Act/Assert (AAA) is a pattern for organizing unit tests. It breaks tests down into three clear and distinct steps:
|
||||||
It breaks tests down into three clear and distinct steps:
|
|
||||||
|
|
||||||
1. Arrange: Perform the setup and initialization required for the test.
|
1. Arrange: Perform the setup and initialization required for the test.
|
||||||
2. Act: Take action(s) required for the test.
|
2. Act: Take action(s) required for the test.
|
||||||
@@ -22,14 +21,9 @@ It breaks tests down into three clear and distinct steps:
|
|||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
This pattern has several significant benefits. It creates a clear separation between a test's
|
This pattern has several significant benefits. It creates a clear separation between a test's setup, operations, and results. This structure makes the code easier to read and understand. If you place the steps in order and format your code to separate them, you can scan a test and quickly comprehend what it does.
|
||||||
setup, operations, and results. This structure makes the code easier to read and understand. If
|
|
||||||
you place the steps in order and format your code to separate them, you can scan a test and
|
|
||||||
quickly comprehend what it does.
|
|
||||||
|
|
||||||
It also enforces a certain degree of discipline when you write your tests. You have to think
|
It also enforces a certain degree of discipline when you write your tests. You have to think clearly about the three steps your test will perform. It makes tests more natural to write at the same time since you already have an outline.
|
||||||
clearly about the three steps your test will perform. It makes tests more natural to write at
|
|
||||||
the same time since you already have an outline.
|
|
||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
@@ -37,8 +31,7 @@ Real world example
|
|||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> Arrange/Act/Assert is a testing pattern that organizes tests into three clear steps for easy
|
> Arrange/Act/Assert is a testing pattern that organizes tests into three clear steps for easy maintenance.
|
||||||
> maintenance.
|
|
||||||
|
|
||||||
WikiWikiWeb says
|
WikiWikiWeb says
|
||||||
|
|
||||||
@@ -76,8 +69,7 @@ public class Cash {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Then we write our unit tests according to Arrange/Act/Assert pattern. Notice the clearly
|
Then we write our unit tests according to Arrange/Act/Assert pattern. Notice the clearly separated steps for each unit test.
|
||||||
separated steps for each unit test.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class CashAAATest {
|
class CashAAATest {
|
||||||
@@ -138,8 +130,7 @@ Use Arrange/Act/Assert pattern when
|
|||||||
## Known uses
|
## Known uses
|
||||||
|
|
||||||
* Widely adopted in software projects using TDD and BDD methodologies.
|
* Widely adopted in software projects using TDD and BDD methodologies.
|
||||||
* Utilized in various programming languages and testing frameworks, such as JUnit (Java), NUnit (.NET), and xUnit
|
* Utilized in various programming languages and testing frameworks, such as JUnit (Java), NUnit (.NET), and xUnit frameworks.
|
||||||
frameworks.
|
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
@@ -152,13 +143,11 @@ Benefits:
|
|||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* May introduce redundancy in tests, as similar arrangements may be repeated across tests.
|
* May introduce redundancy in tests, as similar arrangements may be repeated across tests.
|
||||||
* Some complex tests might not fit neatly into this structure, requiring additional context or setup outside these three
|
* Some complex tests might not fit neatly into this structure, requiring additional context or setup outside these three phases.
|
||||||
phases.
|
|
||||||
|
|
||||||
## Related patterns
|
## Related patterns
|
||||||
|
|
||||||
* [Page Object](https://java-design-patterns.com/patterns/page-object/): A pattern for organizing UI tests that can be
|
* [Page Object](https://java-design-patterns.com/patterns/page-object/): A pattern for organizing UI tests that can be used in conjunction with Arrange/Act/Assert.
|
||||||
used in conjunction with Arrange/Act/Assert.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
Asynchronous method invocation is a pattern where the calling thread is not blocked while waiting results of tasks. The
|
Asynchronous method invocation is a pattern where the calling thread is not blocked while waiting results of tasks. The pattern provides parallel processing of multiple independent tasks and retrieving the results via callbacks or waiting until everything is done.
|
||||||
pattern provides parallel processing of multiple independent tasks and retrieving the results via callbacks or waiting
|
|
||||||
until everything is done.
|
|
||||||
|
|
||||||
## Also known as
|
## Also known as
|
||||||
|
|
||||||
@@ -22,29 +20,21 @@ until everything is done.
|
|||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> Launching space rockets is an exciting business. The mission command gives an order to launch and
|
> Launching space rockets is an exciting business. The mission command gives an order to launch and after some undetermined time, the rocket either launches successfully or fails miserably.
|
||||||
> after some undetermined time, the rocket either launches successfully or fails miserably.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> Asynchronous method invocation starts task processing and returns immediately before the task is
|
> Asynchronous method invocation starts task processing and returns immediately before the task is ready. The results of the task processing are returned to the caller later.
|
||||||
> ready. The results of the task processing are returned to the caller later.
|
|
||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> In multithreaded computer programming, asynchronous method invocation (AMI), also known as
|
> In multithreaded computer programming, asynchronous method invocation (AMI), also known as asynchronous method calls or the asynchronous pattern is a design pattern in which the call site is not blocked while waiting for the called code to finish. Instead, the calling thread is notified when the reply arrives. Polling for a reply is an undesired option.
|
||||||
> asynchronous method calls or the asynchronous pattern is a design pattern in which the call site
|
|
||||||
> is not blocked while waiting for the called code to finish. Instead, the calling thread is
|
|
||||||
> notified when the reply arrives. Polling for a reply is an undesired option.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
In this example, we are launching space rockets and deploying lunar rovers.
|
In this example, we are launching space rockets and deploying lunar rovers.
|
||||||
|
|
||||||
The application demonstrates the async method invocation pattern. The key parts of the pattern are
|
The application demonstrates the async method invocation pattern. The key parts of the pattern are`AsyncResult` which is an intermediate container for an asynchronously evaluated value, `AsyncCallback` which can be provided to be executed on task completion and `AsyncExecutor` that manages the execution of the async tasks.
|
||||||
`AsyncResult` which is an intermediate container for an asynchronously evaluated value,
|
|
||||||
`AsyncCallback` which can be provided to be executed on task completion and `AsyncExecutor` that
|
|
||||||
manages the execution of the async tasks.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public interface AsyncResult<T> {
|
public interface AsyncResult<T> {
|
||||||
@@ -74,8 +64,7 @@ public interface AsyncExecutor {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`ThreadAsyncExecutor` is an implementation of `AsyncExecutor`. Some of its key parts are highlighted
|
`ThreadAsyncExecutor` is an implementation of `AsyncExecutor`. Some of its key parts are highlighted next.
|
||||||
next.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class ThreadAsyncExecutor implements AsyncExecutor {
|
public class ThreadAsyncExecutor implements AsyncExecutor {
|
||||||
@@ -170,16 +159,14 @@ Here's the program console output.
|
|||||||
Use the async method invocation pattern when
|
Use the async method invocation pattern when
|
||||||
|
|
||||||
* When operations do not need to complete before proceeding with the next steps in a program.
|
* When operations do not need to complete before proceeding with the next steps in a program.
|
||||||
* For tasks that are resource-intensive or time-consuming, such as IO operations, network requests, or complex
|
* For tasks that are resource-intensive or time-consuming, such as IO operations, network requests, or complex computations, where making the operation synchronous would significantly impact performance or user experience.
|
||||||
computations, where making the operation synchronous would significantly impact performance or user experience.
|
|
||||||
* In GUI applications to prevent freezing or unresponsiveness during long-running tasks.
|
* In GUI applications to prevent freezing or unresponsiveness during long-running tasks.
|
||||||
* In web applications for non-blocking IO operations.
|
* In web applications for non-blocking IO operations.
|
||||||
|
|
||||||
## Known Uses
|
## Known Uses
|
||||||
|
|
||||||
* Web servers handling HTTP requests asynchronously to improve throughput and reduce latency.
|
* Web servers handling HTTP requests asynchronously to improve throughput and reduce latency.
|
||||||
* Desktop and mobile applications using background threads to perform time-consuming operations without blocking the
|
* Desktop and mobile applications using background threads to perform time-consuming operations without blocking the user interface.
|
||||||
user interface.
|
|
||||||
* Microservices architectures where services perform asynchronous communications via messaging queues or event streams.
|
* Microservices architectures where services perform asynchronous communications via messaging queues or event streams.
|
||||||
* [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html)
|
* [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html)
|
||||||
* [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)
|
* [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)
|
||||||
@@ -190,29 +177,21 @@ Use the async method invocation pattern when
|
|||||||
|
|
||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* Improved Responsiveness: The main thread or application flow remains unblocked, improving the user experience in GUI
|
* Improved Responsiveness: The main thread or application flow remains unblocked, improving the user experience in GUI applications and overall responsiveness.
|
||||||
applications and overall responsiveness.
|
* Better Resource Utilization: By enabling parallel execution, system resources (like CPU and IO) are utilized more efficiently, potentially improving the application's throughput.
|
||||||
* Better Resource Utilization: By enabling parallel execution, system resources (like CPU and IO) are utilized more
|
|
||||||
efficiently, potentially improving the application's throughput.
|
|
||||||
* Scalability: Easier to scale applications, as tasks can be distributed across available resources more effectively.
|
* Scalability: Easier to scale applications, as tasks can be distributed across available resources more effectively.
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* Complexity: Introducing asynchronous operations can complicate the codebase, making it more challenging to understand,
|
* Complexity: Introducing asynchronous operations can complicate the codebase, making it more challenging to understand, debug, and maintain.
|
||||||
debug, and maintain.
|
* Resource Management: Requires careful management of threads or execution contexts, which can introduce overhead and potential resource exhaustion issues.
|
||||||
* Resource Management: Requires careful management of threads or execution contexts, which can introduce overhead and
|
* Error Handling: Asynchronous operations can make error handling more complex, as exceptions may occur in different threads or at different times.
|
||||||
potential resource exhaustion issues.
|
|
||||||
* Error Handling: Asynchronous operations can make error handling more complex, as exceptions may occur in different
|
|
||||||
threads or at different times.
|
|
||||||
|
|
||||||
Related Patterns:
|
Related Patterns:
|
||||||
|
|
||||||
* [Command](https://java-design-patterns.com/patterns/command/): Asynchronous method invocation can be used to implement
|
* [Command](https://java-design-patterns.com/patterns/command/): Asynchronous method invocation can be used to implement the Command pattern, where commands are executed asynchronously.
|
||||||
the Command pattern, where commands are executed asynchronously.
|
* [Observer](https://java-design-patterns.com/patterns/observer/): Asynchronous method invocation can be used to notify observers asynchronously when a subject's state changes.
|
||||||
* [Observer](https://java-design-patterns.com/patterns/observer/): Asynchronous method invocation can be used to notify
|
* [Promise](https://java-design-patterns.com/patterns/promise/): The AsyncResult interface can be considered a form of Promise, representing a value that may not be available yet.
|
||||||
observers asynchronously when a subject's state changes.
|
|
||||||
* [Promise](https://java-design-patterns.com/patterns/promise/): The AsyncResult interface can be considered a form of
|
|
||||||
Promise, representing a value that may not be available yet.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+11
-27
@@ -8,16 +8,13 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
Balking Pattern is used to prevent an object from executing a certain code if it is in an incomplete or inappropriate
|
Balking Pattern is used to prevent an object from executing a certain code if it is in an incomplete or inappropriate state. If the state is not suitable for the action, the method call is ignored (or "balked").
|
||||||
state. If the state is not suitable for the action, the method call is ignored (or "balked").
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> There's a start-button in a washing machine to initiate the laundry washing. When the washing
|
> 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.
|
||||||
> machine is inactive the button works as expected, but if it's already washing the button does
|
|
||||||
> nothing.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
@@ -25,17 +22,11 @@ In plain words
|
|||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> The balking pattern is a software design pattern that only executes an action on an object when
|
> The balking pattern is a software design pattern that only executes an action on an object when the object is in a particular state. For example, if an object reads ZIP files and a calling method invokes a get method on the object when the ZIP file is not open, the object would "balk" at the request.
|
||||||
> the object is in a particular state. For example, if an object reads ZIP files and a calling
|
|
||||||
> method invokes a get method on the object when the ZIP file is not open, the object would "balk"
|
|
||||||
> at the request.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
In this example implementation, `WashingMachine` is an object that has two states in which it can
|
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.
|
||||||
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.
|
|
||||||
|
|
||||||
Here are the relevant parts of the `WashingMachine` class.
|
Here are the relevant parts of the `WashingMachine` class.
|
||||||
|
|
||||||
@@ -125,33 +116,26 @@ Here is the console output of the program.
|
|||||||
Use the Balking pattern when
|
Use the Balking pattern when
|
||||||
|
|
||||||
* You want to invoke an action on an object only when it is in a particular state
|
* You want to invoke an action on an object only when it is in a particular state
|
||||||
* Objects are generally only in a state that is prone to balking temporarily but for an unknown
|
* Objects are generally only in a state that is prone to balking temporarily but for an unknown amount of time
|
||||||
amount of time
|
* In multithreaded applications where certain actions should only proceed when specific conditions are met, and those conditions are expected to change over time due to external factors or concurrent operations.
|
||||||
* In multithreaded applications where certain actions should only proceed when specific conditions are met, and those
|
|
||||||
conditions are expected to change over time due to external factors or concurrent operations.
|
|
||||||
|
|
||||||
## Known Uses:
|
## Known Uses:
|
||||||
|
|
||||||
* Resource pooling, where resources are only allocated if they are in a valid state for allocation.
|
* Resource pooling, where resources are only allocated if they are in a valid state for allocation.
|
||||||
* Thread management, where threads only proceed with tasks if certain conditions (like task availability or resource
|
* Thread management, where threads only proceed with tasks if certain conditions (like task availability or resource locks) are met.
|
||||||
locks) are met.
|
|
||||||
|
|
||||||
## Consequences:
|
## Consequences:
|
||||||
|
|
||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* Reduces unnecessary lock acquisitions in situations where actions cannot proceed, enhancing performance in concurrent
|
* Reduces unnecessary lock acquisitions in situations where actions cannot proceed, enhancing performance in concurrent applications.
|
||||||
applications.
|
|
||||||
* Encourages clear separation of state management and behavior, leading to cleaner code.
|
* Encourages clear separation of state management and behavior, leading to cleaner code.
|
||||||
* Simplifies the handling of operations that should only be performed under certain conditions without cluttering the
|
* Simplifies the handling of operations that should only be performed under certain conditions without cluttering the caller code with state checks.
|
||||||
caller code with state checks.
|
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* Can introduce complexity by obscuring the conditions under which actions are taken or ignored, potentially making the
|
* Can introduce complexity by obscuring the conditions under which actions are taken or ignored, potentially making the system harder to debug and understand.
|
||||||
system harder to debug and understand.
|
* May lead to missed opportunities or actions if the state changes are not properly monitored or if the balking condition is too restrictive.
|
||||||
* May lead to missed opportunities or actions if the state changes are not properly monitored or if the balking
|
|
||||||
condition is too restrictive.
|
|
||||||
|
|
||||||
## Related patterns
|
## Related patterns
|
||||||
|
|
||||||
|
|||||||
+18
-41
@@ -20,20 +20,15 @@ Decouple an abstraction from its implementation so that the two can vary indepen
|
|||||||
|
|
||||||
Real-world example
|
Real-world example
|
||||||
|
|
||||||
> Consider you have a weapon with different enchantments, and you are supposed to allow mixing different weapons with
|
> 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.
|
||||||
> 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.
|
|
||||||
|
|
||||||
In Plain Words
|
In Plain Words
|
||||||
|
|
||||||
> Bridge pattern is about preferring composition to inheritance. Implementation details are pushed from a hierarchy to
|
> Bridge pattern is about preferring composition to inheritance. Implementation details are pushed from a hierarchy to another object with a separate hierarchy.
|
||||||
> another object with a separate hierarchy.
|
|
||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> The bridge pattern is a design pattern used in software engineering that is meant to "decouple an abstraction from its
|
> The bridge pattern is a design pattern used in software engineering that is meant to "decouple an abstraction from its implementation so that the two can vary independently"
|
||||||
> implementation so that the two can vary independently"
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
@@ -206,55 +201,37 @@ The item's glow fades.
|
|||||||
|
|
||||||
Use the Bridge pattern when
|
Use the Bridge pattern when
|
||||||
|
|
||||||
* You want to avoid a permanent binding between an abstraction and its implementation. This might be the case, for
|
* You want to avoid a permanent binding between an abstraction and its implementation. This might be the case, for example, when the implementation must be selected or switched at run-time.
|
||||||
example, when the implementation must be selected or switched at run-time.
|
* Both the abstractions and their implementations should be extensible by subclassing. In this case, the Bridge pattern lets you combine the different abstractions and implementations and extend them independently.
|
||||||
* Both the abstractions and their implementations should be extensible by subclassing. In this case, the Bridge pattern
|
* Changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have to be recompiled.
|
||||||
lets you combine the different abstractions and implementations and extend them independently.
|
* You have a proliferation of classes. Such a class hierarchy indicates the need for splitting an object into two parts. Rumbaugh uses the term "nested generalizations" to refer to such class hierarchies.
|
||||||
* Changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have
|
* You want to share an implementation among multiple objects (perhaps using reference counting), and this fact should be hidden from the client. A simple example is Coplien's String class, in which multiple objects can share the same string representation.
|
||||||
to be recompiled.
|
|
||||||
* You have a proliferation of classes. Such a class hierarchy indicates the need for splitting an object into two parts.
|
|
||||||
Rumbaugh uses the term "nested generalizations" to refer to such class hierarchies.
|
|
||||||
* You want to share an implementation among multiple objects (perhaps using reference counting), and this fact should be
|
|
||||||
hidden from the client. A simple example is Coplien's String class, in which multiple objects can share the same
|
|
||||||
string representation.
|
|
||||||
|
|
||||||
## Known uses
|
## Known uses
|
||||||
|
|
||||||
* GUI Frameworks where the abstraction is the window, and the implementation could be the underlying OS windowing
|
* GUI Frameworks where the abstraction is the window, and the implementation could be the underlying OS windowing system.
|
||||||
system.
|
* Database Drivers where the abstraction is a generic database interface, and the implementations are database-specific drivers.
|
||||||
* Database Drivers where the abstraction is a generic database interface, and the implementations are database-specific
|
* Device Drivers where the abstraction is the device-independent code, and the implementation is the device-dependent code.
|
||||||
drivers.
|
|
||||||
* Device Drivers where the abstraction is the device-independent code, and the implementation is the device-dependent
|
|
||||||
code.
|
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* Decoupling Interface and Implementation: The Bridge pattern enhances modularity by separating the interface (the
|
* Decoupling Interface and Implementation: The Bridge pattern enhances modularity by separating the interface (the high-level operations) from the implementation (the low-level operations).
|
||||||
high-level operations) from the implementation (the low-level operations).
|
|
||||||
* Improved Extensibility: You can extend the abstraction and implementation hierarchies independently.
|
* Improved Extensibility: You can extend the abstraction and implementation hierarchies independently.
|
||||||
* Hiding Implementation Details: Clients only see the abstraction's interface, not its implementation.
|
* Hiding Implementation Details: Clients only see the abstraction's interface, not its implementation.
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* Increased Complexity: The pattern can complicate the system architecture and code, especially for clients unfamiliar
|
* Increased Complexity: The pattern can complicate the system architecture and code, especially for clients unfamiliar with the pattern.
|
||||||
with the pattern.
|
* Runtime Overhead: The extra layer of abstraction can introduce a performance penalty, although it is often negligible in practice.
|
||||||
* Runtime Overhead: The extra layer of abstraction can introduce a performance penalty, although it is often negligible
|
|
||||||
in practice.
|
|
||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
* [Adapter](https://java-design-patterns.com/patterns/adapter/): The Adapter pattern is used to provide a different
|
* [Adapter](https://java-design-patterns.com/patterns/adapter/): The Adapter pattern is used to provide a different interface to an object, while the Bridge pattern is used to separate an object's interface from its implementation.
|
||||||
interface to an object, while the Bridge pattern is used to separate an object's interface from its implementation.
|
* [Strategy](https://java-design-patterns.com/patterns/strategy/): The Strategy pattern is like the Bridge pattern, but with a different intent. Both patterns are based on composition: Strategy uses composition to change the behavior of a class, while Bridge uses composition to separate an abstraction from its implementation.
|
||||||
* [Strategy](https://java-design-patterns.com/patterns/strategy/): The Strategy pattern is like the Bridge pattern, but
|
* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): The Abstract Factory pattern can be used along with the Bridge pattern to create platforms that are independent of the concrete classes used to create their objects.
|
||||||
with a different intent. Both patterns are based on composition: Strategy uses composition to change the behavior of a
|
* [Composite](https://java-design-patterns.com/patterns/composite/): The Bridge pattern is often used with the Composite pattern to model the implementation details of a component.
|
||||||
class, while Bridge uses composition to separate an abstraction from its implementation.
|
|
||||||
* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): The Abstract Factory pattern can be
|
|
||||||
used along with the Bridge pattern to create platforms that are independent of the concrete classes used to create
|
|
||||||
their objects.
|
|
||||||
* [Composite](https://java-design-patterns.com/patterns/composite/): The Bridge pattern is often used with the Composite
|
|
||||||
pattern to model the implementation details of a component.
|
|
||||||
|
|
||||||
## Tutorials
|
## Tutorials
|
||||||
|
|
||||||
|
|||||||
+11
-26
@@ -8,38 +8,30 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
Separate the construction of a complex object from its representation so that the same construction process can create
|
Separate the construction of a complex object from its representation so that the same construction process can create different representations.
|
||||||
different representations.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real-world example
|
Real-world example
|
||||||
|
|
||||||
> Imagine a character generator for a role-playing game. The easiest option is to let the computer create the character
|
> 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.
|
||||||
> 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.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> Allows you to create different flavors of an object while avoiding constructor pollution. Useful when there could be
|
> Allows you to create different flavors of an object while avoiding constructor pollution. Useful when there could be several flavors of an object. Or when there are a lot of steps involved in creation of an object.
|
||||||
> several flavors of an object. Or when there are a lot of steps involved in creation of an object.
|
|
||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> The builder pattern is an object creation software design pattern with the intentions of finding a solution to the
|
> The builder pattern is an object creation software design pattern with the intentions of finding a solution to the telescoping constructor antipattern.
|
||||||
> telescoping constructor antipattern.
|
|
||||||
|
|
||||||
Having said that let me add a bit about what telescoping constructor antipattern is. At one point or the other, we have
|
Having said that let me add a bit about what telescoping constructor antipattern is. At one point or the other, we have all seen a constructor like below:
|
||||||
all seen a constructor like below:
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public Hero(Profession profession,String name,HairType hairType,HairColor hairColor,Armor armor,Weapon weapon){
|
public Hero(Profession profession,String name,HairType hairType,HairColor hairColor,Armor armor,Weapon weapon){
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
As you can see the number of constructor parameters can quickly get out of hand, and it may become difficult to
|
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.
|
||||||
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.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
@@ -124,11 +116,9 @@ var mage=new Hero.Builder(Profession.MAGE,"Riobard").withHairColor(HairColor.BLA
|
|||||||
|
|
||||||
Use the Builder pattern when
|
Use the Builder pattern when
|
||||||
|
|
||||||
* The algorithm for creating a complex object should be independent of the parts that make up the object and how they're
|
* The algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled
|
||||||
assembled
|
|
||||||
* The construction process must allow different representations for the object that's constructed
|
* The construction process must allow different representations for the object that's constructed
|
||||||
* It's particularly useful when a product requires a lot of steps to be created and when these steps need to be executed
|
* It's particularly useful when a product requires a lot of steps to be created and when these steps need to be executed in a specific sequence
|
||||||
in a specific sequence
|
|
||||||
|
|
||||||
## Known Uses
|
## Known Uses
|
||||||
|
|
||||||
@@ -142,8 +132,7 @@ Benefits:
|
|||||||
|
|
||||||
* More control over the construction process compared to other creational patterns
|
* More control over the construction process compared to other creational patterns
|
||||||
* Supports constructing objects step-by-step, defer construction steps or run steps recursively
|
* Supports constructing objects step-by-step, defer construction steps or run steps recursively
|
||||||
* Can construct objects that require a complex assembly of sub-objects. The final product is detached from the parts
|
* Can construct objects that require a complex assembly of sub-objects. The final product is detached from the parts that make it up, as well as their assembly process
|
||||||
that make it up, as well as their assembly process
|
|
||||||
* Single Responsibility Principle. You can isolate complex construction code from the business logic of the product
|
* Single Responsibility Principle. You can isolate complex construction code from the business logic of the product
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
@@ -159,8 +148,7 @@ Trade-offs:
|
|||||||
## Known uses
|
## Known uses
|
||||||
|
|
||||||
* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)
|
* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)
|
||||||
* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) as well as similar
|
* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) as well as similar buffers such as FloatBuffer, IntBuffer and so on.
|
||||||
buffers such as FloatBuffer, IntBuffer and so on.
|
|
||||||
* [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-)
|
* [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-)
|
||||||
* All implementations of [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)
|
* All implementations of [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)
|
||||||
* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)
|
* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)
|
||||||
@@ -168,10 +156,7 @@ Trade-offs:
|
|||||||
|
|
||||||
## Related patterns
|
## Related patterns
|
||||||
|
|
||||||
* [Step Builder](https://java-design-patterns.com/patterns/step-builder/) is a variation of the Builder pattern that
|
* [Step Builder](https://java-design-patterns.com/patterns/step-builder/) is a variation of the Builder pattern that generates a complex object using a step-by-step approach. The Step Builder pattern is a good choice when you need to build an object with a large number of optional parameters, and you want to avoid the telescoping constructor antipattern.
|
||||||
generates a complex object using a step-by-step approach. The Step Builder pattern is a good choice when you need to
|
|
||||||
build an object with a large number of optional parameters, and you want to avoid the telescoping constructor
|
|
||||||
antipattern.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Business Delegate pattern adds an abstraction layer between presentation and business tiers. By using the pattern we
|
The Business Delegate pattern adds an abstraction layer between presentation and business tiers. By using the pattern we gain loose coupling between the tiers and encapsulate knowledge about how to locate, connect to, and interact with the business objects that make up the application.
|
||||||
gain loose coupling between the tiers and encapsulate knowledge about how to locate, connect to, and interact with the
|
|
||||||
business objects that make up the application.
|
|
||||||
|
|
||||||
## Also known as
|
## Also known as
|
||||||
|
|
||||||
@@ -20,9 +18,7 @@ Service Representative
|
|||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> A mobile phone application promises to stream any movie in existence to your device. It captures the user's search
|
> A mobile phone application promises to stream any movie in existence to your device. It captures the user's search string and passes this on to the Business Delegate. The Business Delegate selects the most suitable video streaming service and plays the video from there.
|
||||||
> string and passes this on to the Business Delegate. The Business Delegate selects the most suitable video streaming
|
|
||||||
> service and plays the video from there.
|
|
||||||
|
|
||||||
In Plain Words
|
In Plain Words
|
||||||
|
|
||||||
@@ -30,10 +26,7 @@ In Plain Words
|
|||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> Business Delegate is a Java EE design pattern. This pattern is directing to reduce the coupling in between business
|
> Business Delegate is a Java EE design pattern. This pattern is directing to reduce the coupling in between business services and the connected presentation tier, and to hide the implementation details of services (including lookup and accessibility of EJB architecture). Business Delegates acts as an adaptor to invoke business objects from the presentation tier.
|
||||||
> services and the connected presentation tier, and to hide the implementation details of services (including lookup and
|
|
||||||
> accessibility of EJB architecture). Business Delegates acts as an adaptor to invoke business objects from the
|
|
||||||
> presentation tier.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
@@ -81,8 +74,7 @@ public class BusinessLookup {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The Business Delegate uses a business lookup to route movie playback requests to a suitable
|
The Business Delegate uses a business lookup to route movie playback requests to a suitable video streaming service.
|
||||||
video streaming service.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@@ -173,8 +165,7 @@ Benefits:
|
|||||||
|
|
||||||
* Decoupling of Presentation and Business Tiers: Allows the client tier and business services to evolve independently.
|
* Decoupling of Presentation and Business Tiers: Allows the client tier and business services to evolve independently.
|
||||||
* Location Transparency: Clients remain unaffected by changes in the location or the instantiation of business services.
|
* Location Transparency: Clients remain unaffected by changes in the location or the instantiation of business services.
|
||||||
* Reuse and Scalability: Business Delegate objects can be reused by multiple clients, and the pattern supports load
|
* Reuse and Scalability: Business Delegate objects can be reused by multiple clients, and the pattern supports load balancing and scalability.
|
||||||
balancing and scalability.
|
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
@@ -183,12 +174,9 @@ Trade-offs:
|
|||||||
|
|
||||||
## Related patterns
|
## Related patterns
|
||||||
|
|
||||||
* [Service Locator](https://java-design-patterns.com/patterns/service-locator/): Business Delegate uses Service Locator
|
* [Service Locator](https://java-design-patterns.com/patterns/service-locator/): Business Delegate uses Service Locator to locate business services.
|
||||||
to locate business services.
|
* [Session Facade](https://java-design-patterns.com/patterns/session-facade/): Business Delegate may use Session Facade to provide a unified interface to a set of business services.
|
||||||
* [Session Facade](https://java-design-patterns.com/patterns/session-facade/): Business Delegate may use Session Facade
|
* [Composite Entity](https://java-design-patterns.com/patterns/composite-entity/): Business Delegate may use Composite Entity to manage the state of business services.
|
||||||
to provide a unified interface to a set of business services.
|
|
||||||
* [Composite Entity](https://java-design-patterns.com/patterns/composite-entity/): Business Delegate may use Composite
|
|
||||||
Entity to manage the state of business services.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+11
-26
@@ -14,21 +14,15 @@ Allows encoding behavior as instructions for a virtual machine.
|
|||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> A team is working on a new game where wizards battle against each other. The wizard behavior needs to be carefully
|
> A team is working on a new game where wizards battle against each other. The wizard behavior needs to be carefully adjusted and iterated hundreds of times through playtesting. It's not optimal to ask the programmer to make changes each time the game designer wants to vary the behavior, so the wizard behavior is implemented as a data-driven virtual machine.
|
||||||
> adjusted and iterated hundreds of times through playtesting. It's not optimal to ask the programmer to make changes
|
|
||||||
> each time the game designer wants to vary the behavior, so the wizard behavior is implemented as a data-driven virtual
|
|
||||||
> machine.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> Bytecode pattern enables behavior driven by data instead of code.
|
> Bytecode pattern enables behavior driven by data instead of code.
|
||||||
|
|
||||||
[Gameprogrammingpatterns.com](https://gameprogrammingpatterns.com/bytecode.html) documentation
|
[Gameprogrammingpatterns.com](https://gameprogrammingpatterns.com/bytecode.html) documentation states:
|
||||||
states:
|
|
||||||
|
|
||||||
> An instruction set defines the low-level operations that can be performed. A series of instructions is encoded as a
|
> An instruction set defines the low-level operations that can be performed. A series of instructions is encoded as a sequence of bytes. A virtual machine executes these instructions one at a time, using a stack for intermediate values. By combining instructions, complex high-level behavior can be defined.
|
||||||
> sequence of bytes. A virtual machine executes these instructions one at a time, using a stack for intermediate values.
|
|
||||||
> By combining instructions, complex high-level behavior can be defined.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
@@ -60,9 +54,7 @@ public class Wizard {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, we show the available instructions for our virtual machine. Each of the instructions has its own semantics on how
|
Next, we show the available instructions for our virtual machine. Each of the instructions has its own semantics on how it operates with the stack data. For example, the ADD instruction takes the top two items from the stack, adds them together and pushes the result to the stack.
|
||||||
it operates with the stack data. For example, the ADD instruction takes the top two items from the stack, adds them
|
|
||||||
together and pushes the result to the stack.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@@ -85,8 +77,7 @@ public enum Instruction {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
At the heart of our example is the `VirtualMachine` class. It takes instructions as input and executes them to provide
|
At the heart of our example is the `VirtualMachine` class. It takes instructions as input and executes them to provide the game object behavior.
|
||||||
the game object behavior.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@@ -227,13 +218,11 @@ Here is the console output.
|
|||||||
|
|
||||||
## Applicability
|
## Applicability
|
||||||
|
|
||||||
Use the Bytecode pattern when you have a lot of behavior you need to define and your game’s implementation language
|
Use the Bytecode pattern when you have a lot of behavior you need to define and your game’s implementation language isn’t a good fit because:
|
||||||
isn’t a good fit because:
|
|
||||||
|
|
||||||
* It’s too low-level, making it tedious or error-prone to program in.
|
* It’s too low-level, making it tedious or error-prone to program in.
|
||||||
* Iterating on it takes too long due to slow compile times or other tooling issues.
|
* Iterating on it takes too long due to slow compile times or other tooling issues.
|
||||||
* It has too much trust. If you want to ensure the behavior being defined can’t break the game, you need to sandbox it
|
* It has too much trust. If you want to ensure the behavior being defined can’t break the game, you need to sandbox it from the rest of the codebase.
|
||||||
from the rest of the codebase.
|
|
||||||
|
|
||||||
## Known Uses
|
## Known Uses
|
||||||
|
|
||||||
@@ -251,18 +240,14 @@ Benefits:
|
|||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* Overhead: Running bytecode typically involves more overhead than running native code, potentially affecting
|
* Overhead: Running bytecode typically involves more overhead than running native code, potentially affecting performance.
|
||||||
performance.
|
|
||||||
* Complexity: Implementing and maintaining a VM adds complexity to the system.
|
* Complexity: Implementing and maintaining a VM adds complexity to the system.
|
||||||
|
|
||||||
## Related patterns
|
## Related patterns
|
||||||
|
|
||||||
* [Interpreter](https://java-design-patterns.com/patterns/interpreter/) is often used within the implementation of VMs
|
* [Interpreter](https://java-design-patterns.com/patterns/interpreter/) is often used within the implementation of VMs to interpret bytecode instructions
|
||||||
to interpret bytecode instructions
|
* [Command](https://java-design-patterns.com/patterns/command/): Bytecode instructions can be seen as commands executed by the VM.
|
||||||
* [Command](https://java-design-patterns.com/patterns/command/): Bytecode instructions can be seen as commands executed
|
* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): VMs may use factory methods to instantiate operations or instructions defined in the bytecode.
|
||||||
by the VM.
|
|
||||||
* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): VMs may use factory methods to
|
|
||||||
instantiate operations or instructions defined in the bytecode.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+18
-48
@@ -10,9 +10,7 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The caching pattern avoids expensive re-acquisition of resources by not releasing them immediately after use. The
|
The caching pattern avoids expensive re-acquisition of resources by not releasing them immediately after use. The resources retain their identity, are kept in some fast-access storage, and are re-used to avoid having to acquire them again.
|
||||||
resources retain their identity, are kept in some fast-access storage, and are re-used to avoid having to acquire them
|
|
||||||
again.
|
|
||||||
|
|
||||||
## Also known as
|
## Also known as
|
||||||
|
|
||||||
@@ -23,10 +21,7 @@ again.
|
|||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> A team is working on a website that provides new homes for abandoned cats. People can post their cats on the website
|
> A team is working on a website that provides new homes for abandoned cats. People can post their cats on the website after registering, but all the new posts require approval from one of the site moderators. The user accounts of the site moderators contain a specific flag and the data is stored in a MongoDB database. Checking for the moderator flag each time a post is viewed becomes expensive, and it's a good idea to utilize caching here.
|
||||||
> after registering, but all the new posts require approval from one of the site moderators. The user accounts of the
|
|
||||||
> site moderators contain a specific flag and the data is stored in a MongoDB database. Checking for the moderator flag
|
|
||||||
> each time a post is viewed becomes expensive, and it's a good idea to utilize caching here.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
@@ -34,17 +29,11 @@ In plain words
|
|||||||
|
|
||||||
Wikipedia says:
|
Wikipedia says:
|
||||||
|
|
||||||
> In computing, a cache is a hardware or software component that stores data so that future requests for that data can
|
> 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.
|
||||||
> 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.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
Let's first look at the data layer of our application. The interesting classes are `UserAccount` which is a simple Java
|
Let's first look at the data layer of our application. The interesting classes are `UserAccount` which is a simple Java object containing the user account details, and `DbManager` interface which handles reading and writing of these objects to/from database.
|
||||||
object containing the user account details, and `DbManager` interface which handles reading and writing of these objects
|
|
||||||
to/from database.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@@ -78,18 +67,11 @@ In the example, we are demonstrating various different caching policies
|
|||||||
|
|
||||||
* Write-through writes data to the cache and DB in a single transaction
|
* Write-through writes data to the cache and DB in a single transaction
|
||||||
* Write-around writes data immediately into the DB instead of the cache
|
* Write-around writes data immediately into the DB instead of the cache
|
||||||
* Write-behind writes data into the cache initially whilst the data is only written into the DB
|
* Write-behind writes data into the cache initially whilst the data is only written into the DB when the cache is full
|
||||||
when the cache is full
|
* Cache-aside pushes the responsibility of keeping the data synchronized in both data sources to the application itself
|
||||||
* Cache-aside pushes the responsibility of keeping the data synchronized in both data sources to
|
* Read-through strategy is also included in the aforementioned strategies, and it returns data from the cache to the caller if it exists, otherwise queries from DB and stores it into the cache for future use.
|
||||||
the application itself
|
|
||||||
* Read-through strategy is also included in the aforementioned strategies, and it returns data from
|
|
||||||
the cache to the caller if it exists, otherwise queries from DB and stores it into the cache for
|
|
||||||
future use.
|
|
||||||
|
|
||||||
The cache implementation in `LruCache` is a hash table accompanied by a doubly linked-list. The linked-list helps in
|
The cache implementation in `LruCache` is a hash table accompanied by a doubly linked-list. The linked-list helps in capturing and maintaining the LRU data in the cache. When data is queried (from the cache), added (to the cache), or updated, the data is moved to the front of the list to depict itself as the most-recently-used data. The LRU data is always at the end of the list.
|
||||||
capturing and maintaining the LRU data in the cache. When data is queried (from the cache), added (to the cache), or
|
|
||||||
updated, the data is moved to the front of the list to depict itself as the most-recently-used data. The LRU data is
|
|
||||||
always at the end of the list.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@@ -229,10 +211,7 @@ public class CacheStore {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`AppManager` helps to bridge the gap in communication between the main class and the application's back-end. DB
|
`AppManager` helps to bridge the gap in communication between the main class and the application's back-end. DB connection is initialized through this class. The chosen caching strategy/policy is also initialized here. Before the cache can be used, the size of the cache has to be set. Depending on the chosen caching policy, `AppManager` will call the appropriate function in the `CacheStore` class.
|
||||||
connection is initialized through this class. The chosen caching strategy/policy is also initialized here. Before the
|
|
||||||
cache can be used, the size of the cache has to be set. Depending on the chosen caching policy, `AppManager` will call
|
|
||||||
the appropriate function in the `CacheStore` class.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@@ -341,8 +320,7 @@ public class App {
|
|||||||
Use the Caching pattern when
|
Use the Caching pattern when
|
||||||
|
|
||||||
* Repetitious acquisition, initialization, and release of the same resource cause unnecessary performance overhead
|
* Repetitious acquisition, initialization, and release of the same resource cause unnecessary performance overhead
|
||||||
* In scenarios where the cost of recomputing or re-fetching data is significantly higher than storing and retrieving it
|
* In scenarios where the cost of recomputing or re-fetching data is significantly higher than storing and retrieving it from cache
|
||||||
from cache
|
|
||||||
* For read-heavy applications with relatively static data or data that changes infrequently
|
* For read-heavy applications with relatively static data or data that changes infrequently
|
||||||
|
|
||||||
## Known Uses
|
## Known Uses
|
||||||
@@ -350,36 +328,28 @@ Use the Caching pattern when
|
|||||||
* Web page caching to reduce server load and improve response time
|
* Web page caching to reduce server load and improve response time
|
||||||
* Database query caching to avoid repeated expensive SQL queries
|
* Database query caching to avoid repeated expensive SQL queries
|
||||||
* Caching results of CPU-intensive computations
|
* Caching results of CPU-intensive computations
|
||||||
* Content Delivery Networks (CDNs) for caching static resources like images, CSS, and JavaScript files closer to the end
|
* Content Delivery Networks (CDNs) for caching static resources like images, CSS, and JavaScript files closer to the end users
|
||||||
users
|
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* Improved Performance: Significantly reduces data access latency, leading to faster application performance
|
* Improved Performance: Significantly reduces data access latency, leading to faster application performance
|
||||||
* Reduced Load: Decreases the load on the underlying data source, which can lead to cost savings and increased longevity
|
* Reduced Load: Decreases the load on the underlying data source, which can lead to cost savings and increased longevity of the resource
|
||||||
of the resource
|
* Scalability: Enhances the scalability of applications by efficiently handling increases in load without proportional increases in resource utilization
|
||||||
* Scalability: Enhances the scalability of applications by efficiently handling increases in load without proportional
|
|
||||||
increases in resource utilization
|
|
||||||
|
|
||||||
Trade-Offs:
|
Trade-Offs:
|
||||||
|
|
||||||
* Complexity: Introduces complexity in terms of cache invalidation, consistency, and synchronization
|
* Complexity: Introduces complexity in terms of cache invalidation, consistency, and synchronization
|
||||||
* Resource Utilization: Requires additional memory or storage resources to maintain the cache
|
* Resource Utilization: Requires additional memory or storage resources to maintain the cache
|
||||||
* Stale Data: There's a risk of serving outdated data if the cache is not properly invalidated or updated when the
|
* Stale Data: There's a risk of serving outdated data if the cache is not properly invalidated or updated when the underlying data changes
|
||||||
underlying data changes
|
|
||||||
|
|
||||||
## Related patterns
|
## Related patterns
|
||||||
|
|
||||||
* [Proxy](https://java-design-patterns.com/patterns/proxy/): Caching can be implemented using the Proxy pattern, where
|
* [Proxy](https://java-design-patterns.com/patterns/proxy/): Caching can be implemented using the Proxy pattern, where the proxy object intercepts requests and returns cached data if available
|
||||||
the proxy object intercepts requests and returns cached data if available
|
* [Observer](https://java-design-patterns.com/patterns/observer/): Can be used to notify the cache when the underlying data changes, so that it can be updated or invalidated accordingly
|
||||||
* [Observer](https://java-design-patterns.com/patterns/observer/): Can be used to notify the cache when the underlying
|
* [Decorator](https://java-design-patterns.com/patterns/decorator/): Can be used to add caching behavior to an existing object without modifying its code
|
||||||
data changes, so that it can be updated or invalidated accordingly
|
* [Strategy](https://java-design-patterns.com/patterns/strategy/): Different caching strategies can be implemented using the Strategy pattern, allowing the application to switch between them at runtime
|
||||||
* [Decorator](https://java-design-patterns.com/patterns/decorator/): Can be used to add caching behavior to an existing
|
|
||||||
object without modifying its code
|
|
||||||
* [Strategy](https://java-design-patterns.com/patterns/strategy/): Different caching strategies can be implemented using
|
|
||||||
the Strategy pattern, allowing the application to switch between them at runtime
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+10
-20
@@ -11,8 +11,7 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
Callback is a piece of executable code that is passed as an argument to other code, which is expected to call back (
|
Callback is a piece of executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at some convenient time.
|
||||||
execute) the argument at some convenient time.
|
|
||||||
|
|
||||||
## Also known as
|
## Also known as
|
||||||
|
|
||||||
@@ -23,8 +22,7 @@ execute) the argument at some convenient time.
|
|||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> We need to be notified after the executing task has finished. We pass a callback method for the executor and wait for
|
> 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.
|
||||||
> it to call back on us.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
@@ -32,8 +30,7 @@ In plain words
|
|||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> In computer programming, a callback, also known as a "call-after" function, is any executable code that is passed as
|
> In computer programming, a callback, also known as a "call-after" function, is any executable code that is passed as an argument to other code; that other code is expected to call back (execute) the argument at a given time.
|
||||||
> an argument to other code; that other code is expected to call back (execute) the argument at a given time.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
@@ -92,15 +89,13 @@ Use the Callback pattern when
|
|||||||
|
|
||||||
* GUI frameworks often use callbacks for event handling, such as user interactions (clicks, key presses)
|
* GUI frameworks often use callbacks for event handling, such as user interactions (clicks, key presses)
|
||||||
* Node.js heavily relies on callbacks for non-blocking I/O operations
|
* Node.js heavily relies on callbacks for non-blocking I/O operations
|
||||||
* Frameworks that deal with asynchronous operations, like Promises in JavaScript, use callbacks to handle the resolution
|
* Frameworks that deal with asynchronous operations, like Promises in JavaScript, use callbacks to handle the resolution or rejection of asynchronous tasks
|
||||||
or rejection of asynchronous tasks
|
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* Decouples the execution logic of an operation from the signaling or notification logic, enhancing modularity and
|
* Decouples the execution logic of an operation from the signaling or notification logic, enhancing modularity and reusability
|
||||||
reusability
|
|
||||||
* Facilitates asynchronous processing, improving the responsiveness and scalability of applications
|
* Facilitates asynchronous processing, improving the responsiveness and scalability of applications
|
||||||
* Enables a reactive programming model where components can react to events as they occur
|
* Enables a reactive programming model where components can react to events as they occur
|
||||||
|
|
||||||
@@ -108,21 +103,16 @@ Trade-offs:
|
|||||||
|
|
||||||
* Callback hell or pyramid of doom: Deeply nested callbacks can lead to code that is hard to read and maintain
|
* Callback hell or pyramid of doom: Deeply nested callbacks can lead to code that is hard to read and maintain
|
||||||
* Inversion of control can lead to harder-to-follow code flow, making debugging more challenging
|
* Inversion of control can lead to harder-to-follow code flow, making debugging more challenging
|
||||||
* Potential issues with error handling, especially in languages or environments where exceptions are used, as errors
|
* Potential issues with error handling, especially in languages or environments where exceptions are used, as errors might need to be propagated through callbacks
|
||||||
might need to be propagated through callbacks
|
|
||||||
|
|
||||||
## Related patterns
|
## Related patterns
|
||||||
|
|
||||||
[Observer](https://java-design-patterns.com/patterns/observer/): Callbacks can be seen as a more dynamic and lightweight
|
* [Observer](https://java-design-patterns.com/patterns/observer/): Callbacks can be seen as a more dynamic and lightweight form of the Observer pattern, with the ability to subscribe and unsubscribe callback functions dynamically
|
||||||
form of the Observer pattern, with the ability to subscribe and unsubscribe callback functions dynamically
|
* [Command](https://java-design-patterns.com/patterns/command/): Callbacks can be implemented as Command objects in scenarios where more flexibility or statefulness is required in the callback operation
|
||||||
[Command](https://java-design-patterns.com/patterns/command/): Callbacks can be implemented as Command objects in
|
* [Promise](https://java-design-patterns.com/patterns/promise/): In some languages or frameworks, Promises or Futures can be used to handle asynchronous operations more cleanly, often using callbacks for success or failure cases
|
||||||
scenarios where more flexibility or statefulness is required in the callback operation
|
|
||||||
[Promise](https://java-design-patterns.com/patterns/promise/): In some languages or frameworks, Promises or Futures can
|
|
||||||
be used to handle asynchronous operations more cleanly, often using callbacks for success or failure cases
|
|
||||||
|
|
||||||
## Real world examples
|
## Real world examples
|
||||||
|
|
||||||
* [CyclicBarrier](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29)
|
* [CyclicBarrier](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29) constructor can accept a callback that will be triggered every time a barrier is tripped.
|
||||||
constructor can accept a callback that will be triggered every time a barrier is tripped.
|
|
||||||
* [JavaScript: The Good Parts](https://amzn.to/3TiQV61)
|
* [JavaScript: The Good Parts](https://amzn.to/3TiQV61)
|
||||||
* [Node.js Design Patterns - Third edition: Design and implement production-grade Node.js applications using proven patterns and techniques](https://amzn.to/3VssjKG)
|
* [Node.js Design Patterns - Third edition: Design and implement production-grade Node.js applications using proven patterns and techniques](https://amzn.to/3VssjKG)
|
||||||
@@ -15,28 +15,21 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to
|
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
|
||||||
handle the request. Chain the receiving objects and pass the request along the chain until an object
|
|
||||||
handles it.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real-world example
|
Real-world example
|
||||||
|
|
||||||
> The Orc King gives loud orders to his army. The closest one to react is the commander, then
|
> The Orc King gives loud orders to his army. The closest one to react is the commander, then an officer, and then a soldier. The commander, officer, and soldier form a chain of responsibility.
|
||||||
> an officer, and then a soldier. The commander, officer, and soldier form a chain of responsibility.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> It helps to build a chain of objects. A request enters from one end and keeps going from an object
|
> It helps to build a chain of objects. A request enters from one end and keeps going from an object to another until it finds a suitable handler.
|
||||||
> to another until it finds a suitable handler.
|
|
||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of
|
> In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain.
|
||||||
> a source of command objects and a series of processing objects. Each processing object contains
|
|
||||||
> logic that defines the types of command objects that it can handle; the rest are passed to the
|
|
||||||
> next processing object in the chain.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
@@ -165,8 +158,7 @@ Orc soldier handling request "collect tax"
|
|||||||
|
|
||||||
Use Chain of Responsibility when
|
Use Chain of Responsibility when
|
||||||
|
|
||||||
* More than one object may handle a request, and the handler isn't known a priori. The handler should be ascertained
|
* More than one object may handle a request, and the handler isn't known a priori. The handler should be ascertained automatically.
|
||||||
automatically.
|
|
||||||
* You want to issue a request to one of several objects without specifying the receiver explicitly.
|
* You want to issue a request to one of several objects without specifying the receiver explicitly.
|
||||||
* The set of objects that can handle a request should be specified dynamically.
|
* The set of objects that can handle a request should be specified dynamically.
|
||||||
|
|
||||||
@@ -184,25 +176,20 @@ Use Chain of Responsibility when
|
|||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* Reduced coupling. The sender of a request does not need to know the concrete handler that will process the request.
|
* Reduced coupling. The sender of a request does not need to know the concrete handler that will process the request.
|
||||||
* Increased flexibility in assigning responsibilities to objects. You can add or change responsibilities for handling a
|
* Increased flexibility in assigning responsibilities to objects. You can add or change responsibilities for handling a request by changing the members and order of the chain.
|
||||||
request by changing the members and order of the chain.
|
|
||||||
* Allows you to set a default handler if no concrete handler can handle the request.
|
* Allows you to set a default handler if no concrete handler can handle the request.
|
||||||
|
|
||||||
Trade-Offs:
|
Trade-Offs:
|
||||||
|
|
||||||
* It can be challenging to debug and understand the flow, especially if the chain is long and complex.
|
* It can be challenging to debug and understand the flow, especially if the chain is long and complex.
|
||||||
* The request might end up unhandled if the chain doesn't include a catch-all handler.
|
* The request might end up unhandled if the chain doesn't include a catch-all handler.
|
||||||
* Performance concerns might arise due to potentially going through several handlers before finding the right one, or
|
* Performance concerns might arise due to potentially going through several handlers before finding the right one, or not finding it at all.
|
||||||
not finding it at all.
|
|
||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
[Command](https://java-design-patterns.com/patterns/command/): can be used to encapsulate a request as an object, which
|
* [Command](https://java-design-patterns.com/patterns/command/): can be used to encapsulate a request as an object, which might be passed along the chain.
|
||||||
might be passed along the chain.
|
* [Composite](https://java-design-patterns.com/patterns/composite/): the Chain of Responsibility is often applied in conjunction with the Composite pattern.
|
||||||
[Composite](https://java-design-patterns.com/patterns/composite/): the Chain of Responsibility is often applied in
|
* [Decorator](https://java-design-patterns.com/patterns/decorator/): decorators can be chained in a similar manner as responsibilities in the Chain of Responsibility pattern.
|
||||||
conjunction with the Composite pattern.
|
|
||||||
[Decorator](https://java-design-patterns.com/patterns/decorator/): decorators can be chained in a similar manner as
|
|
||||||
responsibilities in the Chain of Responsibility pattern.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+14
-42
@@ -14,41 +14,25 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Circuit Breaker pattern aims to prevent a software system from making calls to a part of the system that is either
|
The Circuit Breaker pattern aims to prevent a software system from making calls to a part of the system that is either failing or showing signs of distress. It is a way to gracefully degrade functionality when a dependent service is not responding, rather than failing completely.
|
||||||
failing or showing signs of distress. It is a way to gracefully degrade functionality when a dependent service is not
|
|
||||||
responding, rather than failing completely.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> Imagine a web application that has both local files/images and remote services that are used for
|
> Imagine a web application that has both local files/images and remote services that are used for fetching data. These remote services may be either healthy and responsive at times, or may become slow and unresponsive at some point of time due to variety of reasons. So if one of the remote services is slow or not responding successfully, our application will try to fetch response from the remote service using multiple threads/processes, soon all of them will hang (also called[thread starvation](https://en.wikipedia.org/wiki/Starvation_(computer_science))) causing our entire web application to crash. We should be able to detect this situation and show the user an appropriate message so that he/she can explore other parts of the app unaffected by the remote serv'ice failure. Meanwhile, the other services that are working normally, should keep functioning unaffected by this failure.
|
||||||
> fetching data. These remote services may be either healthy and responsive at times, or may become
|
|
||||||
> slow and unresponsive at some point of time due to variety of reasons. So if one of the remote
|
|
||||||
> services is slow or not responding successfully, our application will try to fetch response from
|
|
||||||
> the remote service using multiple threads/processes, soon all of them will hang (also called
|
|
||||||
> [thread starvation](https://en.wikipedia.org/wiki/Starvation_(computer_science))) causing our entire web application
|
|
||||||
> to crash. We should be able to detect this situation and show the user an appropriate message so that he/she can
|
|
||||||
> explore other parts of the app unaffected by the remote serv'ice failure. Meanwhile, the other services that are
|
|
||||||
> working normally, should keep functioning unaffected by this failure.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> Circuit Breaker allows graceful handling of failed remote services. It's especially useful when
|
> Circuit Breaker allows graceful handling of failed remote services. It's especially useful when all parts of our application are highly decoupled from each other, and failure of one component doesn't mean the other parts will stop working.
|
||||||
> all parts of our application are highly decoupled from each other, and failure of one component
|
|
||||||
> doesn't mean the other parts will stop working.
|
|
||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> Circuit breaker is a design pattern used in modern software development. It is used to detect
|
> Circuit breaker is a design pattern used in modern software development. It is used to detect failures and encapsulates the logic of preventing a failure from constantly recurring, during maintenance, temporary external system failure or unexpected system difficulties.
|
||||||
> failures and encapsulates the logic of preventing a failure from constantly recurring, during
|
|
||||||
> maintenance, temporary external system failure or unexpected system difficulties.
|
|
||||||
|
|
||||||
## Programmatic Example
|
## Programmatic Example
|
||||||
|
|
||||||
So, how does this all come together? With the above example in mind we will imitate the
|
So, how does this all come together? With the above example in mind we will imitate the functionality in a simple example. A monitoring service mimics the web app and makes both local and remote calls.
|
||||||
functionality in a simple example. A monitoring service mimics the web app and makes both local and
|
|
||||||
remote calls.
|
|
||||||
|
|
||||||
The service architecture is as follows:
|
The service architecture is as follows:
|
||||||
|
|
||||||
@@ -164,8 +148,7 @@ public class MonitoringService {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
As it can be seen, it does the call to get local resources directly, but it wraps the call to
|
As it can be seen, it does the call to get local resources directly, but it wraps the call to remote (costly) service in a circuit breaker object, which prevents faults as follows:
|
||||||
remote (costly) service in a circuit breaker object, which prevents faults as follows:
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class DefaultCircuitBreaker implements CircuitBreaker {
|
public class DefaultCircuitBreaker implements CircuitBreaker {
|
||||||
@@ -295,22 +278,15 @@ public class DefaultCircuitBreaker implements CircuitBreaker {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
How does the above pattern prevent failures? Let's understand via this finite state machine
|
How does the above pattern prevent failures? Let's understand via this finite state machine implemented by it.
|
||||||
implemented by it.
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- We initialize the Circuit Breaker object with certain parameters: `timeout`, `failureThreshold` and `retryTimePeriod`
|
- We initialize the Circuit Breaker object with certain parameters: `timeout`, `failureThreshold` and `retryTimePeriod`which help determine how resilient the API is.
|
||||||
which help determine how resilient the API is.
|
|
||||||
- Initially, we are in the `closed` state and nos remote calls to the API have occurred.
|
- Initially, we are in the `closed` state and nos remote calls to the API have occurred.
|
||||||
- Every time the call succeeds, we reset the state to as it was in the beginning.
|
- Every time the call succeeds, we reset the state to as it was in the beginning.
|
||||||
- If the number of failures cross a certain threshold, we move to the `open` state, which acts just like an open circuit
|
- If the number of failures cross a certain threshold, we move to the `open` state, which acts just like an open circuit and prevents remote service calls from being made, thus saving resources. (Here, we return the response called ```stale response from API```)
|
||||||
and prevents remote service calls from being made, thus saving resources. (Here, we return the response
|
- Once we exceed the retry timeout period, we move to the `half-open` state and make another call to the remote service again to check if the service is working so that we can serve fresh content. A failure sets it back to `open` state and another attempt is made after retry timeout period, while a success sets it to `closed` state so that everything starts working normally again.
|
||||||
called ```stale response from API```)
|
|
||||||
- Once we exceed the retry timeout period, we move to the `half-open` state and make another call to the remote service
|
|
||||||
again to check if the service is working so that we can serve fresh content. A failure sets it back to `open` state
|
|
||||||
and another attempt is made after retry timeout period, while a success sets it to `closed` state so that everything
|
|
||||||
starts working normally again.
|
|
||||||
|
|
||||||
## Class diagram
|
## Class diagram
|
||||||
|
|
||||||
@@ -340,18 +316,14 @@ Benefits:
|
|||||||
|
|
||||||
Trade-Offs:
|
Trade-Offs:
|
||||||
|
|
||||||
* The complexity of the system increases as the pattern requires additional logic to detect failures and manage the
|
* The complexity of the system increases as the pattern requires additional logic to detect failures and manage the state of the circuit breaker
|
||||||
state of the circuit breaker
|
* May lead to system degradation if not properly configured, as legitimate requests might be blocked if the circuit is open
|
||||||
* May lead to system degradation if not properly configured, as legitimate requests might be blocked if the circuit is
|
|
||||||
open
|
|
||||||
* Requires careful tuning of thresholds and timeout periods to balance between responsiveness and protection
|
* Requires careful tuning of thresholds and timeout periods to balance between responsiveness and protection
|
||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
- [Retry Pattern](https://github.com/iluwatar/java-design-patterns/tree/master/retry): Can be used in conjunction with
|
- [Retry Pattern](https://github.com/iluwatar/java-design-patterns/tree/master/retry): Can be used in conjunction with the Circuit Breaker pattern to retry failed operations before opening the circuit
|
||||||
the Circuit Breaker pattern to retry failed operations before opening the circuit
|
- [Bulkhead Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead): Can be used to isolate different parts of the system to prevent failures from spreading across the system
|
||||||
- [Bulkhead Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead): Can be used to isolate
|
|
||||||
different parts of the system to prevent failures from spreading across the system
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+11
-32
@@ -13,35 +13,21 @@ tags:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Client Session design pattern aims to maintain a user's state and data across multiple requests within a web
|
The Client Session design pattern aims to maintain a user's state and data across multiple requests within a web application, ensuring a continuous and personalized user experience.
|
||||||
application, ensuring a continuous and personalized user experience.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real-World Example
|
Real-World Example
|
||||||
|
|
||||||
> You're looking to create a data management app allowing users to send requests to the server to modify and make
|
> You're looking to create a data management app allowing users to send requests to the server to modify and make changes to data stored on their devices. These requests are small and the data is individual to each user, negating the need for a large scale database implementation. Using the client session pattern, you are able to handle multiple concurrent requests, load balancing clients across different servers with ease due to servers remaining stateless. You also remove the need to store session IDs on the server side due to clients providing all the information that a server needs to perform their process.
|
||||||
> changes to data stored on their devices. These requests are small and the data is individual to each user, negating
|
|
||||||
> the need for a large scale database implementation. Using the client session pattern, you are able to handle multiple
|
|
||||||
> concurrent requests, load balancing clients across different servers with ease due to servers remaining stateless. You
|
|
||||||
> also remove the need to store session IDs on the server side due to clients providing all the information that a
|
|
||||||
> server needs to perform their process.
|
|
||||||
|
|
||||||
In Plain words
|
In Plain words
|
||||||
|
|
||||||
> Instead of storing information about the current client and the information being accessed on the server, it is
|
> Instead of storing information about the current client and the information being accessed on the server, it is maintained client side only. Client has to send session data with each request to the server and has to send an updated state back to the client, which is stored on the clients machine. The server doesn't have to store the client information. ([ref](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-client))
|
||||||
> maintained client side only. Client has to send session data with each request to the server and has to send an
|
|
||||||
> updated state back to the client, which is stored on the clients machine. The server doesn't have to store the client
|
|
||||||
> information. ([ref](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-client))
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
Here is the sample code to describe the client-session pattern. In the below code we are first creating an instance of
|
Here is the sample code to describe the client-session pattern. In the below code we are first creating an instance of the Server. This server instance will then be used to get Session objects for two clients. As you can see from the code below the Session object can be used to store any relevant information that are required by the server to process the client request. These session objects will then be passed on with every Request to the server. The Request will have the Session object that stores the relevant client details along with the required data for processing the request. The session information in every request helps the server identify the client and process the request accordingly.
|
||||||
the Server. This server instance will then be used to get Session objects for two clients. As you can see from the code
|
|
||||||
below the Session object can be used to store any relevant information that are required by the server to process the
|
|
||||||
client request. These session objects will then be passed on with every Request to the server. The Request will have the
|
|
||||||
Session object that stores the relevant client details along with the required data for processing the request. The
|
|
||||||
session information in every request helps the server identify the client and process the request accordingly.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class App {
|
public class App {
|
||||||
@@ -107,27 +93,20 @@ Use the client state pattern when:
|
|||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* Improved server performance by reducing the need to store user state on the server.
|
* Improved server performance by reducing the need to store user state on the server.
|
||||||
* Enhanced user experience through personalized content and seamless navigation across different parts of the
|
* Enhanced user experience through personalized content and seamless navigation across different parts of the application.
|
||||||
application.
|
|
||||||
* Flexibility in managing sessions through various client-side storage mechanisms (e.g., cookies, Web Storage API).
|
* Flexibility in managing sessions through various client-side storage mechanisms (e.g., cookies, Web Storage API).
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* Potential security risks if sensitive information is stored in client sessions without proper encryption and
|
* Potential security risks if sensitive information is stored in client sessions without proper encryption and validation.
|
||||||
validation.
|
* Dependence on client-side capabilities and settings, such as cookie policies, which can vary across browsers and user configurations.
|
||||||
* Dependence on client-side capabilities and settings, such as cookie policies, which can vary across browsers and user
|
* Increased complexity in session management logic, especially in handling session expiration, renewal, and synchronization across multiple devices or tabs.
|
||||||
configurations.
|
|
||||||
* Increased complexity in session management logic, especially in handling session expiration, renewal, and
|
|
||||||
synchronization across multiple devices or tabs.
|
|
||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
* Server Session: Often used in conjunction with the Client Session pattern to provide a balance between client-side
|
* Server Session: Often used in conjunction with the Client Session pattern to provide a balance between client-side efficiency and server-side control.
|
||||||
efficiency and server-side control.
|
* [Singleton](https://java-design-patterns.com/patterns/singleton/): Ensuring a single instance of a user's session throughout the application.
|
||||||
* [Singleton](https://java-design-patterns.com/patterns/singleton/): Ensuring a single instance of a user's session
|
* [State](https://java-design-patterns.com/patterns/state/): Managing state transitions in a session, such as authenticated, guest, or expired states.
|
||||||
throughout the application.
|
|
||||||
* [State](https://java-design-patterns.com/patterns/state/): Managing state transitions in a session, such as
|
|
||||||
authenticated, guest, or expired states.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
@@ -14,35 +14,25 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
Aims to simplify methods that collect information by passing a single collection object through various method calls,
|
Aims to simplify methods that collect information by passing a single collection object through various method calls, allowing them to add results to this collection rather than each method creating its own collection.
|
||||||
allowing them to add results to this collection rather than each method creating its own collection.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
### Real-world example
|
### Real-world example
|
||||||
|
|
||||||
Within a large corporate building, there exists a global printer queue that is a collection of all the printing jobs
|
Within a large corporate building, there exists a global printer queue that is a collection of all the printing jobs that are currently pending. Various floors contain different models of printers, each having a different printing policy. We must construct a program that can continually add appropriate printing jobs to a collection, which is called the *collecting parameter*.
|
||||||
that are currently pending. Various floors contain different models of printers, each having a different printing
|
|
||||||
policy. We must construct a program that can continually add appropriate printing jobs to a collection, which is called
|
|
||||||
the *collecting parameter*.
|
|
||||||
|
|
||||||
### In plain words
|
### In plain words
|
||||||
|
|
||||||
Instead of having one giant method that contains numerous policies for collecting information into a variable, we can
|
Instead of having one giant method that contains numerous policies for collecting information into a variable, we can create numerous smaller functions that each take parameter, and append new information. We can pass the parameter to all of these smaller functions and by the end, we will have what we wanted originally. This time, the code is cleaner and easier to understand. Because the larger function has been broken down, the code is also easier to modify as changes are localised to the smaller functions.
|
||||||
create numerous smaller functions that each take parameter, and append new information. We can pass the parameter to all
|
|
||||||
of these smaller functions and by the end, we will have what we wanted originally. This time, the code is cleaner and
|
|
||||||
easier to understand. Because the larger function has been broken down, the code is also easier to modify as changes are
|
|
||||||
localised to the smaller functions.
|
|
||||||
|
|
||||||
### Wikipedia says
|
### Wikipedia says
|
||||||
|
|
||||||
In the Collecting Parameter idiom a collection (list, map, etc.) is passed repeatedly as a parameter to a method which
|
In the Collecting Parameter idiom a collection (list, map, etc.) is passed repeatedly as a parameter to a method which adds items to the collection.
|
||||||
adds items to the collection.
|
|
||||||
|
|
||||||
### Programmatic example
|
### Programmatic example
|
||||||
|
|
||||||
Coding our example from above, we may use the collection `result` as a collecting parameter. The following restrictions
|
Coding our example from above, we may use the collection `result` as a collecting parameter. The following restrictions are implemented:
|
||||||
are implemented:
|
|
||||||
|
|
||||||
- If an A4 paper is coloured, it must also be single-sided. All other non-coloured papers are accepted
|
- If an A4 paper is coloured, it must also be single-sided. All other non-coloured papers are accepted
|
||||||
- A3 papers must be non-coloured and single-sided
|
- A3 papers must be non-coloured and single-sided
|
||||||
@@ -85,8 +75,7 @@ public class App {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
We use the `addA4Paper`, `addA3Paper`, and `addA2Paper` methods to populate the `result` collecting parameter with the
|
We use the `addA4Paper`, `addA3Paper`, and `addA2Paper` methods to populate the `result` collecting parameter with the appropriate print jobs as per the policy described previously. The three policies are encoded below,
|
||||||
appropriate print jobs as per the policy described previously. The three policies are encoded below,
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class App {
|
public class App {
|
||||||
@@ -162,12 +151,9 @@ public class App {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Each method takes a collecting parameter as an argument. It then adds elements, taken from a global variable, to this
|
Each method takes a collecting parameter as an argument. It then adds elements, taken from a global variable, to this collecting parameter if each element satisfies a given criteria. These methods can have whatever policy the client desires.
|
||||||
collecting parameter if each element satisfies a given criteria. These methods can have whatever policy the client
|
|
||||||
desires.
|
|
||||||
|
|
||||||
In this programmatic example, three print jobs are added to the queue. Only the first two print jobs should be added to
|
In this programmatic example, three print jobs are added to the queue. Only the first two print jobs should be added to the collecting parameter as per the policy. The elements of the `result` variable after execution are,
|
||||||
the collecting parameter as per the policy. The elements of the `result` variable after execution are,
|
|
||||||
|
|
||||||
| paperSize | pageCount | isDoubleSided | isColour |
|
| paperSize | pageCount | isDoubleSided | isColour |
|
||||||
|-----------|-----------|---------------|----------|
|
|-----------|-----------|---------------|----------|
|
||||||
@@ -185,26 +171,19 @@ which is what we expected.
|
|||||||
Use the Collecting Parameter design pattern when
|
Use the Collecting Parameter design pattern when
|
||||||
|
|
||||||
- When multiple methods produce a collection of results and you want to aggregate these results in a unified manner.
|
- When multiple methods produce a collection of results and you want to aggregate these results in a unified manner.
|
||||||
- In scenarios where reducing the number of collections created by methods can improve memory efficiency and
|
- In scenarios where reducing the number of collections created by methods can improve memory efficiency and performance.
|
||||||
performance.
|
- When you're refactoring large methods that perform multiple tasks, including the collection of results from various operations.
|
||||||
- When you're refactoring large methods that perform multiple tasks, including the collection of results from various
|
|
||||||
operations.
|
|
||||||
|
|
||||||
## Tutorials
|
## Tutorials
|
||||||
|
|
||||||
Tutorials for this method are found in:
|
Tutorials for this method are found in:
|
||||||
|
|
||||||
- [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf) by Joshua Kerivsky
|
- [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf) by Joshua Kerivsky
|
||||||
- [Smalltalk Best Practice Patterns](https://ptgmedia.pearsoncmg.com/images/9780134769042/samplepages/013476904X.pdf) by
|
- [Smalltalk Best Practice Patterns](https://ptgmedia.pearsoncmg.com/images/9780134769042/samplepages/013476904X.pdf) by Kent Beck
|
||||||
Kent Beck
|
|
||||||
|
|
||||||
## Known uses
|
## Known uses
|
||||||
|
|
||||||
Joshua Kerivsky gives a real-world example in his book 'Refactoring to Patterns'. He gives an example of using the
|
Joshua Kerivsky gives a real-world example in his book 'Refactoring to Patterns'. He gives an example of using the Collecting Parameter Design Pattern to create a `toString()` method for an XML tree. Without using this design pattern, this would require a bulky function with conditionals and concatenation that would worsen code readability. Such a method can be broken down into smaller methods, each appending their own set of information to the collecting parameter. See this in [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf).
|
||||||
Collecting Parameter Design Pattern to create a `toString()` method for an XML tree. Without using this design pattern,
|
|
||||||
this would require a bulky function with conditionals and concatenation that would worsen code readability. Such a
|
|
||||||
method can be broken down into smaller methods, each appending their own set of information to the collecting parameter.
|
|
||||||
See this in [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf).
|
|
||||||
|
|
||||||
Other examples include:
|
Other examples include:
|
||||||
|
|
||||||
@@ -223,23 +202,18 @@ Benefits:
|
|||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
- Increases coupling between the caller and the methods being called since they must agree on the collection to use.
|
- Increases coupling between the caller and the methods being called since they must agree on the collection to use.
|
||||||
- May introduce side effects in methods if not carefully managed, as methods are no longer self-contained in their
|
- May introduce side effects in methods if not carefully managed, as methods are no longer self-contained in their result handling.
|
||||||
result handling.
|
|
||||||
|
|
||||||
## Related patterns
|
## Related patterns
|
||||||
|
|
||||||
- [Composite](https://java-design-patterns.com/patterns/composite/): Can be used in tandem with Collecting Parameter
|
- [Composite](https://java-design-patterns.com/patterns/composite/): Can be used in tandem with Collecting Parameter when dealing with hierarchical structures, allowing results to be collected across a composite structure.
|
||||||
when dealing with hierarchical structures, allowing results to be collected across a composite structure.
|
- [Visitor](https://java-design-patterns.com/patterns/visitor/): Often used together, where Visitor handles traversal and operations on a structure, and Collecting Parameter accumulates the results.
|
||||||
- [Visitor](https://java-design-patterns.com/patterns/visitor/): Often used together, where Visitor handles traversal
|
- [Command](https://java-design-patterns.com/patterns/command/): Commands may utilize Collecting Parameter to aggregate results from multiple operations executed by the command objects.
|
||||||
and operations on a structure, and Collecting Parameter accumulates the results.
|
|
||||||
- [Command](https://java-design-patterns.com/patterns/command/): Commands may utilize Collecting Parameter to aggregate
|
|
||||||
results from multiple operations executed by the command objects.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
- [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf) by Joshua Kerivsky
|
- [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf) by Joshua Kerivsky
|
||||||
- [Smalltalk Best Practice Patterns](https://ptgmedia.pearsoncmg.com/images/9780134769042/samplepages/013476904X.pdf) by
|
- [Smalltalk Best Practice Patterns](https://ptgmedia.pearsoncmg.com/images/9780134769042/samplepages/013476904X.pdf) by Kent Beck
|
||||||
Kent Beck
|
|
||||||
- [Wiki](https://wiki.c2.com/?CollectingParameter)
|
- [Wiki](https://wiki.c2.com/?CollectingParameter)
|
||||||
- [Refactoring: Improving the Design of Existing Code](https://amzn.to/3TVEgaB)
|
- [Refactoring: Improving the Design of Existing Code](https://amzn.to/3TVEgaB)
|
||||||
- [Clean Code: A Handbook of Agile Software Craftsmanship](https://amzn.to/4aApLP0)
|
- [Clean Code: A Handbook of Agile Software Craftsmanship](https://amzn.to/4aApLP0)
|
||||||
@@ -9,44 +9,31 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Collection Pipeline design pattern is intended to process collections of data by chaining together operations in a
|
The Collection Pipeline design pattern is intended to process collections of data by chaining together operations in a sequence where the output of one operation is the input for the next. It promotes a declarative approach to handling collections, focusing on what should be done rather than how.
|
||||||
sequence where the output of one operation is the input for the next. It promotes a declarative approach to handling
|
|
||||||
collections, focusing on what should be done rather than how.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real-world example
|
Real-world example
|
||||||
|
|
||||||
> Imagine you're in a large library filled with books, and you're tasked with finding all the science fiction books
|
> Imagine you're in a large library filled with books, and you're tasked with finding all the science fiction books published after 2000, then arranging them by author name in alphabetical order, and finally picking out the top 5 based on their popularity or ratings.
|
||||||
> published after 2000, then arranging them by author name in alphabetical order, and finally picking out the top 5 based
|
|
||||||
> on their popularity or ratings.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> The Collection Pipeline pattern involves processing data by passing it through a series of operations, each
|
> The Collection Pipeline pattern involves processing data by passing it through a series of operations, each transforming the data in sequence, much like an assembly line in a factory.
|
||||||
> transforming the data in sequence, much like an assembly line in a factory.
|
|
||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> In software engineering, a pipeline consists of a chain of processing elements (processes, threads, coroutines,
|
> In software engineering, a pipeline consists of a chain of processing elements (processes, threads, coroutines, functions, etc.), arranged so that the output of each element is the input of the next; the name is by analogy to a physical pipeline. Usually some amount of buffering is provided between consecutive elements. The information that flows in these pipelines is often a stream of records, bytes, or bits, and the elements of a pipeline may be called filters; this is also called the pipe(s) and filters design pattern. Connecting elements into a pipeline is analogous to function composition.
|
||||||
> functions, etc.), arranged so that the output of each element is the input of the next; the name is by analogy to a
|
|
||||||
> physical pipeline. Usually some amount of buffering is provided between consecutive elements. The information that flows
|
|
||||||
> in these pipelines is often a stream of records, bytes, or bits, and the elements of a pipeline may be called filters;
|
|
||||||
> this is also called the pipe(s) and filters design pattern. Connecting elements into a pipeline is analogous to function
|
|
||||||
> composition.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
The Collection Pipeline pattern is implemented in this code example by using Java's Stream API to perform a series of
|
The Collection Pipeline pattern is implemented in this code example by using Java's Stream API to perform a series of transformations on a collection of Car objects. The transformations are chained together to form a pipeline. Here's a breakdown of how it's done:
|
||||||
transformations on a collection of Car objects. The transformations are chained together to form a pipeline. Here's a
|
|
||||||
breakdown of how it's done:
|
|
||||||
|
|
||||||
1. Creation of Cars: A list of Car objects is created using the `CarFactory.createCars()` method.
|
1. Creation of Cars: A list of Car objects is created using the `CarFactory.createCars()` method.
|
||||||
|
|
||||||
`var cars = CarFactory.createCars();`
|
`var cars = CarFactory.createCars();`
|
||||||
|
|
||||||
2. Filtering and Transforming: The `FunctionalProgramming.getModelsAfter2000(cars)` method filters the cars to only
|
2. Filtering and Transforming: The `FunctionalProgramming.getModelsAfter2000(cars)` method filters the cars to only include those made after the year 2000, and then transforms the filtered cars into a list of their model names.
|
||||||
include those made after the year 2000, and then transforms the filtered cars into a list of their model names.
|
|
||||||
|
|
||||||
`var modelsFunctional = FunctionalProgramming.getModelsAfter2000(cars);`
|
`var modelsFunctional = FunctionalProgramming.getModelsAfter2000(cars);`
|
||||||
|
|
||||||
@@ -73,9 +60,7 @@ public static Map<Category, List<Car>>getGroupingOfCarsByCategory(List<Car> cars
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Filtering, Sorting and Transforming: The `FunctionalProgramming.getSedanCarsOwnedSortedByDate(List.of(john))` method
|
4. Filtering, Sorting and Transforming: The `FunctionalProgramming.getSedanCarsOwnedSortedByDate(List.of(john))` method filters the cars owned by a person to only include sedans, sorts them by date, and then transforms the sorted cars into a list of Car objects.
|
||||||
filters the cars owned by a person to only include sedans, sorts them by date, and then transforms the sorted cars
|
|
||||||
into a list of Car objects.
|
|
||||||
|
|
||||||
`var sedansOwnedFunctional = FunctionalProgramming.getSedanCarsOwnedSortedByDate(List.of(john));`
|
`var sedansOwnedFunctional = FunctionalProgramming.getSedanCarsOwnedSortedByDate(List.of(john));`
|
||||||
|
|
||||||
@@ -90,8 +75,7 @@ public static List<Car> getSedanCarsOwnedSortedByDate(List<Person> persons){
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In each of these methods, the Collection Pipeline pattern is used to perform a series of operations on the collection of
|
In each of these methods, the Collection Pipeline pattern is used to perform a series of operations on the collection of cars in a declarative manner, which improves readability and maintainability.
|
||||||
cars in a declarative manner, which improves readability and maintainability.
|
|
||||||
|
|
||||||
## Class diagram
|
## Class diagram
|
||||||
|
|
||||||
@@ -99,9 +83,7 @@ cars in a declarative manner, which improves readability and maintainability.
|
|||||||
|
|
||||||
## Applicability
|
## Applicability
|
||||||
|
|
||||||
This pattern is applicable in scenarios involving bulk data operations such as filtering, mapping, sorting, or reducing
|
This pattern is applicable in scenarios involving bulk data operations such as filtering, mapping, sorting, or reducing collections. It's particularly useful in data analysis, transformation tasks, and where a sequence of operations needs to be applied to each element of a collection.
|
||||||
collections. It's particularly useful in data analysis, transformation tasks, and where a sequence of operations needs
|
|
||||||
to be applied to each element of a collection.
|
|
||||||
|
|
||||||
## Known Uses
|
## Known Uses
|
||||||
|
|
||||||
@@ -121,21 +103,15 @@ Benefits:
|
|||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* Performance Overhead: Chaining multiple operations can introduce overhead compared to traditional loops, especially
|
* Performance Overhead: Chaining multiple operations can introduce overhead compared to traditional loops, especially for short pipelines or very large collections.
|
||||||
for short pipelines or very large collections.
|
* Debugging Difficulty: Debugging a chain of operations might be more challenging due to the lack of intermediate variables.
|
||||||
* Debugging Difficulty: Debugging a chain of operations might be more challenging due to the lack of intermediate
|
* Limited to Collections: Primarily focused on collections, and its utility might be limited outside of collection processing.
|
||||||
variables.
|
|
||||||
* Limited to Collections: Primarily focused on collections, and its utility might be limited outside of collection
|
|
||||||
processing.
|
|
||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
* [Builder](https://java-design-patterns.com/patterns/builder/): Similar fluent interface style but used for object
|
* [Builder](https://java-design-patterns.com/patterns/builder/): Similar fluent interface style but used for object construction.
|
||||||
construction.
|
* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Conceptually similar in chaining handlers, but applied to object requests rather than data collection processing.
|
||||||
* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Conceptually similar in
|
* [Strategy](https://java-design-patterns.com/patterns/strategy/): Can be used within a pipeline stage to encapsulate different algorithms that can be selected at runtime.
|
||||||
chaining handlers, but applied to object requests rather than data collection processing.
|
|
||||||
* [Strategy](https://java-design-patterns.com/patterns/strategy/): Can be used within a pipeline stage to encapsulate
|
|
||||||
different algorithms that can be selected at runtime.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+10
-22
@@ -14,16 +14,13 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Combinator pattern is intended to enable complex functionalities by combining simple functions into more complex
|
The Combinator pattern is intended to enable complex functionalities by combining simple functions into more complex ones. It aims to achieve modularization and reusability by breaking down a task into simpler, interchangeable components that can be composed in various ways.
|
||||||
ones. It aims to achieve modularization and reusability by breaking down a task into simpler, interchangeable components
|
|
||||||
that can be composed in various ways.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> In computer science, combinatory logic is used as a simplified model of computation, used in computability theory and
|
> In computer science, combinatory logic is used as a simplified model of computation, used in computability theory and proof theory. Despite its simplicity, combinatory logic captures many essential features of computation.
|
||||||
> proof theory. Despite its simplicity, combinatory logic captures many essential features of computation.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
@@ -31,13 +28,11 @@ In plain words
|
|||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> A combinator is a higher-order function that uses only function application and earlier defined combinators to define
|
> A combinator is a higher-order function that uses only function application and earlier defined combinators to define a result from its arguments.
|
||||||
> a result from its arguments.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
Translating the combinator example above. First of all, we have an interface consist of several
|
Translating the combinator example above. First of all, we have an interface consist of several methods `contains`, `not`, `or`, `and` .
|
||||||
methods `contains`, `not`, `or`, `and` .
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// Functional interface to find lines in text.
|
// Functional interface to find lines in text.
|
||||||
@@ -84,8 +79,7 @@ public interface Finder {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Then we have also another combinator for some complex finders `advancedFinder`, `filteredFinder`, `specializedFinder`
|
Then we have also another combinator for some complex finders `advancedFinder`, `filteredFinder`, `specializedFinder` and `expandedFinder`.
|
||||||
and `expandedFinder`.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// Complex finders consisting of simple finder.
|
// Complex finders consisting of simple finder.
|
||||||
@@ -181,9 +175,7 @@ the result of expanded(or)query[[many,Annabel]]is[It was many and many a year ag
|
|||||||
the result of filtered query is[But we loved with a love that was more than love-]
|
the result of filtered query is[But we loved with a love that was more than love-]
|
||||||
```
|
```
|
||||||
|
|
||||||
Now we can design our app to with the queries finding
|
Now we can design our app to with the queries finding feature `expandedFinder`, `specializedFinder`, `advancedFinder`, `filteredFinder` which are all derived from `contains`, `or`, `not`, `and`.
|
||||||
feature `expandedFinder`, `specializedFinder`, `advancedFinder`, `filteredFinder` which are all derived
|
|
||||||
from `contains`, `or`, `not`, `and`.
|
|
||||||
|
|
||||||
## Class diagram
|
## Class diagram
|
||||||
|
|
||||||
@@ -199,8 +191,7 @@ This pattern is applicable in scenarios where:
|
|||||||
|
|
||||||
## Known Uses
|
## Known Uses
|
||||||
|
|
||||||
* Functional programming languages like Haskell and Scala extensively use combinators for tasks ranging from parsing to
|
* Functional programming languages like Haskell and Scala extensively use combinators for tasks ranging from parsing to UI construction.
|
||||||
UI construction.
|
|
||||||
* In domain-specific languages, particularly those involved in parsing, such as parsing expression grammars.
|
* In domain-specific languages, particularly those involved in parsing, such as parsing expression grammars.
|
||||||
* In libraries for functional programming in languages like JavaScript, Python, and Ruby.
|
* In libraries for functional programming in languages like JavaScript, Python, and Ruby.
|
||||||
* java.util.function.Function#compose
|
* java.util.function.Function#compose
|
||||||
@@ -222,12 +213,9 @@ Trade-offs:
|
|||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
[Strategy](https://java-design-patterns.com/patterns/strategy/): Both involve selecting an algorithm at runtime, but
|
* [Strategy](https://java-design-patterns.com/patterns/strategy/): Both involve selecting an algorithm at runtime, but Combinator uses composition of functions.
|
||||||
Combinator uses composition of functions.
|
* [Decorator](https://java-design-patterns.com/patterns/decorator/): Similar to Combinator in enhancing functionality, but Decorator focuses on object augmentation.
|
||||||
[Decorator](https://java-design-patterns.com/patterns/decorator/): Similar to Combinator in enhancing functionality, but
|
* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Relies on chaining objects, whereas Combinator chains functions.
|
||||||
Decorator focuses on object augmentation.
|
|
||||||
[Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Relies on chaining
|
|
||||||
objects, whereas Combinator chains functions.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+10
-34
@@ -13,16 +13,13 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Command design pattern encapsulates a request as an object, thereby allowing for parameterization of clients with
|
The Command design pattern encapsulates a request as an object, thereby allowing for parameterization of clients with queues, requests, and operations. It also allows for the support of undoable operations.
|
||||||
queues, requests, and operations. It also allows for the support of undoable operations.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real-world example
|
Real-world example
|
||||||
|
|
||||||
> There is a wizard casting spells on a goblin. The spells are executed on the goblin one by one.
|
> There is a wizard casting spells on a goblin. The spells are executed on the goblin one by one. The first spell shrinks the goblin and the second makes him invisible. Then the wizard reverses the spells one by one. Each spell here is a command object that can be undone.
|
||||||
> The first spell shrinks the goblin and the second makes him invisible. Then the wizard reverses
|
|
||||||
> the spells one by one. Each spell here is a command object that can be undone.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
@@ -30,9 +27,7 @@ In plain words
|
|||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> In object-oriented programming, the command pattern is a behavioral design pattern in which an
|
> In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time.
|
||||||
> object is used to encapsulate all information needed to perform an action or trigger an event at
|
|
||||||
> a later time.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
@@ -201,27 +196,11 @@ Goblin,[size=normal][visibility=visible]
|
|||||||
|
|
||||||
Use the Command pattern when you want to:
|
Use the Command pattern when you want to:
|
||||||
|
|
||||||
* Parameterize objects by an action to perform. You can express such parameterization in a
|
* Parameterize objects by an action to perform. You can express such parameterization in a procedural language with a callback function, that is, a function that's registered somewhere to be called at a later point. Commands are an object-oriented replacement for callbacks.
|
||||||
procedural language with a callback function, that is, a function that's registered somewhere to be
|
* Specify, queue, and execute requests at different times. A Command object can have a life independent of the original request. If the receiver of a request can be represented in an address space-independent way, then you can transfer a command object for the request to a different process and fulfill the request there.
|
||||||
called at a later point. Commands are an object-oriented replacement for callbacks.
|
* Support undo. The Command's execute operation can store state for reversing its effects in the command itself. The Command interface must have an added un-execute operation that reverses the effects of a previous call to execute. The executed commands are stored in a history list. Unlimited-level undo and redo functionality is achieved by traversing this list backward and forward calling un-execute and execute, respectively.
|
||||||
* Specify, queue, and execute requests at different times. A Command object can have a life
|
* Support logging changes so that they can be reapplied in case of a system crash. By augmenting the Command interface with load and store operations, you can keep a persistent log of changes. Recovering from a crash involves reloading logged commands from the disk and re-executing them with the execute operation.
|
||||||
independent of the original request. If the receiver of a request can be represented in an address
|
* Structure a system around high-level operations build on primitive operations. Such a structure is common in information systems that support transactions. A transaction encapsulates a set of data changes. The Command pattern offers a way to model transactions. Commands have a common interface, letting you invoke all transactions the same way. The pattern also makes it easy to extend the system with new transactions.
|
||||||
space-independent way, then you can transfer a command object for the request to a different process
|
|
||||||
and fulfill the request there.
|
|
||||||
* Support undo. The Command's execute operation can store state for reversing its effects in the
|
|
||||||
command itself. The Command interface must have an added un-execute operation that reverses the
|
|
||||||
effects of a previous call to execute. The executed commands are stored in a history list.
|
|
||||||
Unlimited-level undo and redo functionality is achieved by traversing this list backward and forward
|
|
||||||
calling un-execute and execute, respectively.
|
|
||||||
* Support logging changes so that they can be reapplied in case of a system crash. By augmenting the
|
|
||||||
Command interface with load and store operations, you can keep a persistent log of changes.
|
|
||||||
Recovering from a crash involves reloading logged commands from the disk and re-executing them with
|
|
||||||
the execute operation.
|
|
||||||
* Structure a system around high-level operations build on primitive operations. Such a structure is
|
|
||||||
common in information systems that support transactions. A transaction encapsulates a set of data
|
|
||||||
changes. The Command pattern offers a way to model transactions. Commands have a common interface,
|
|
||||||
letting you invoke all transactions the same way. The pattern also makes it easy to extend the
|
|
||||||
system with new transactions.
|
|
||||||
* Keep a history of requests.
|
* Keep a history of requests.
|
||||||
* Implement callback functionality.
|
* Implement callback functionality.
|
||||||
* Implement the undo functionality.
|
* Implement the undo functionality.
|
||||||
@@ -251,12 +230,9 @@ Trade-offs:
|
|||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
* [Composite](https://java-design-patterns.com/patterns/composite/): Commands can be composed using the Composite
|
* [Composite](https://java-design-patterns.com/patterns/composite/): Commands can be composed using the Composite pattern to create macro commands.
|
||||||
pattern
|
|
||||||
to create macro commands.
|
|
||||||
* [Memento](https://java-design-patterns.com/patterns/memento/): Can be used for implementing undo mechanisms.
|
* [Memento](https://java-design-patterns.com/patterns/memento/): Can be used for implementing undo mechanisms.
|
||||||
* [Observer](https://java-design-patterns.com/patterns/observer/): The pattern can be observed for changes that trigger
|
* [Observer](https://java-design-patterns.com/patterns/observer/): The pattern can be observed for changes that trigger commands.
|
||||||
commands.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+15
-46
@@ -15,52 +15,29 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The intent of the Commander pattern in the context of distributed transactions is to manage and coordinate complex
|
The intent of the Commander pattern in the context of distributed transactions is to manage and coordinate complex transactions across multiple distributed components or services, ensuring consistency and integrity of the overall transaction. It encapsulates transaction commands and coordination logic, facilitating the implementation of distributed transaction protocols like two-phase commit or Saga.
|
||||||
transactions across multiple distributed components or services, ensuring consistency and integrity of the overall
|
|
||||||
transaction. It encapsulates transaction commands and coordination logic, facilitating the implementation of distributed
|
|
||||||
transaction protocols like two-phase commit or Saga.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real-world example
|
Real-world example
|
||||||
|
|
||||||
> Imagine organizing a large international music festival where various bands from around the world are scheduled to
|
> Imagine organizing a large international music festival where various bands from around the world are scheduled to perform. Each band's arrival, soundcheck, and performance are like individual transactions in a distributed system. The festival organizer acts as the "Commander," coordinating these transactions to ensure that if a band's flight is delayed (akin to a transaction failure), there's a backup plan, such as rescheduling or swapping time slots with another band (compensating actions), to keep the overall schedule intact. This setup mirrors the Commander pattern in distributed transactions, where various components must be coordinated to achieve a successful outcome despite individual failures.
|
||||||
> perform. Each band's arrival, soundcheck, and performance are like individual transactions in a distributed system. The
|
|
||||||
> festival organizer acts as the "Commander," coordinating these transactions to ensure that if a band's flight is
|
|
||||||
> delayed (akin to a transaction failure), there's a backup plan, such as rescheduling or swapping time slots with another
|
|
||||||
> band (compensating actions), to keep the overall schedule intact. This setup mirrors the Commander pattern in
|
|
||||||
> distributed transactions, where various components must be coordinated to achieve a successful outcome despite
|
|
||||||
> individual failures.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> The Commander pattern turns a request into a stand-alone object, allowing for the parameterization of commands,
|
> The Commander pattern turns a request into a stand-alone object, allowing for the parameterization of commands, queueing of actions, and the implementation of undo operations.
|
||||||
> queueing of actions, and the implementation of undo operations.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
Managing transactions across different services in a distributed system, such as an e-commerce platform with separate
|
Managing transactions across different services in a distributed system, such as an e-commerce platform with separate Payment and Shipping microservices, requires careful coordination to avoid issues. When a user places an order but one service (e.g., Payment) is unavailable while the other (e.g., Shipping) is ready, we need a robust solution to handle this discrepancy.
|
||||||
Payment and Shipping microservices, requires careful coordination to avoid issues. When a user places an order but one
|
|
||||||
service (e.g., Payment) is unavailable while the other (e.g., Shipping) is ready, we need a robust solution to handle
|
|
||||||
this discrepancy.
|
|
||||||
|
|
||||||
A strategy to address this involves using a Commander component that orchestrates the process. Initially, the order is
|
A strategy to address this involves using a Commander component that orchestrates the process. Initially, the order is processed by the available service (Shipping in this case). The commander then attempts to synchronize the order with the currently unavailable service (Payment) by storing the order details in a database or queueing it for future processing. This queueing system must also account for possible failures in adding requests to the queue.
|
||||||
processed by the available service (Shipping in this case). The commander then attempts to synchronize the order with
|
|
||||||
the currently unavailable service (Payment) by storing the order details in a database or queueing it for future
|
|
||||||
processing. This queueing system must also account for possible failures in adding requests to the queue.
|
|
||||||
|
|
||||||
The commander repeatedly tries to process the queued orders to ensure both services eventually reflect the same
|
The commander repeatedly tries to process the queued orders to ensure both services eventually reflect the same transaction data. This process involves ensuring idempotence, meaning that even if the same order synchronization request is made multiple times, it will only be executed once, preventing duplicate transactions. The goal is to achieve eventual consistency across services, where all systems are synchronized over time despite initial failures or delays.
|
||||||
transaction data. This process involves ensuring idempotence, meaning that even if the same order synchronization
|
|
||||||
request is made multiple times, it will only be executed once, preventing duplicate transactions. The goal is to achieve
|
|
||||||
eventual consistency across services, where all systems are synchronized over time despite initial failures or delays.
|
|
||||||
|
|
||||||
In the provided code, the Commander pattern is used to handle distributed transactions across multiple services (
|
In the provided code, the Commander pattern is used to handle distributed transactions across multiple services (PaymentService, ShippingService, MessagingService, EmployeeHandle). Each service has its own database and can throw exceptions to simulate failures.
|
||||||
PaymentService, ShippingService, MessagingService, EmployeeHandle). Each service has its own database and can throw
|
|
||||||
exceptions to simulate failures.
|
|
||||||
|
|
||||||
The Commander class is the central part of this pattern. It takes instances of all services and their databases, along
|
The Commander class is the central part of this pattern. It takes instances of all services and their databases, along with some configuration parameters. The placeOrder method in the Commander class is used to place an order, which involves interacting with all the services.
|
||||||
with some configuration parameters. The placeOrder method in the Commander class is used to place an order, which
|
|
||||||
involves interacting with all the services.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Commander {
|
public class Commander {
|
||||||
@@ -84,9 +61,7 @@ public class Order {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Each service (e.g., PaymentService, ShippingService, MessagingService, EmployeeHandle) has its own database and can
|
Each service (e.g., PaymentService, ShippingService, MessagingService, EmployeeHandle) has its own database and can throw exceptions to simulate failures. For example, the PaymentService might throw a DatabaseUnavailableException if its database is unavailable.
|
||||||
throw exceptions to simulate failures. For example, the PaymentService might throw a DatabaseUnavailableException if its
|
|
||||||
database is unavailable.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class PaymentService {
|
public class PaymentService {
|
||||||
@@ -94,8 +69,7 @@ public class PaymentService {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The DatabaseUnavailableException, ItemUnavailableException, and ShippingNotPossibleException classes represent different
|
The DatabaseUnavailableException, ItemUnavailableException, and ShippingNotPossibleException classes represent different types of exceptions that can occur.
|
||||||
types of exceptions that can occur.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class DatabaseUnavailableException extends Exception {
|
public class DatabaseUnavailableException extends Exception {
|
||||||
@@ -111,8 +85,7 @@ public class ShippingNotPossibleException extends Exception {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In the main method of each class (AppQueueFailCases, AppShippingFailCases), different scenarios are simulated by
|
In the main method of each class (AppQueueFailCases, AppShippingFailCases), different scenarios are simulated by creating instances of the Commander class with different configurations and calling the placeOrder method.
|
||||||
creating instances of the Commander class with different configurations and calling the placeOrder method.
|
|
||||||
|
|
||||||
## Class diagram
|
## Class diagram
|
||||||
|
|
||||||
@@ -129,18 +102,15 @@ Use the Commander pattern for distributed transactions when:
|
|||||||
## Known Uses
|
## Known Uses
|
||||||
|
|
||||||
* Two-Phase Commit (2PC) Protocols: Coordinating commit or rollback across distributed databases or services.
|
* Two-Phase Commit (2PC) Protocols: Coordinating commit or rollback across distributed databases or services.
|
||||||
* Saga Pattern Implementations: Managing long-lived business processes that span multiple microservices, with each step
|
* Saga Pattern Implementations: Managing long-lived business processes that span multiple microservices, with each step having a compensating action for rollback.
|
||||||
having a compensating action for rollback.
|
* Distributed Transactions in Microservices Architecture: Coordinating complex operations across microservices while maintaining data integrity and consistency.
|
||||||
* Distributed Transactions in Microservices Architecture: Coordinating complex operations across microservices while
|
|
||||||
maintaining data integrity and consistency.
|
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* Provides a clear mechanism for managing complex distributed transactions, enhancing system reliability.
|
* Provides a clear mechanism for managing complex distributed transactions, enhancing system reliability.
|
||||||
* Enables the implementation of compensating transactions, which are crucial for maintaining consistency in long-lived
|
* Enables the implementation of compensating transactions, which are crucial for maintaining consistency in long-lived transactions.
|
||||||
transactions.
|
|
||||||
* Facilitates the integration of heterogeneous systems within a transactional context.
|
* Facilitates the integration of heterogeneous systems within a transactional context.
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
@@ -151,8 +121,7 @@ Trade-offs:
|
|||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
[Saga Pattern](https://java-design-patterns.com/patterns/saga/): Often discussed in tandem with the Commander pattern
|
[Saga Pattern](https://java-design-patterns.com/patterns/saga/): Often discussed in tandem with the Commander pattern for distributed transactions, focusing on long-lived transactions with compensating actions.
|
||||||
for distributed transactions, focusing on long-lived transactions with compensating actions.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+17
-43
@@ -16,37 +16,25 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Component design pattern aims to organize code into reusable, interchangeable components, promoting flexibility and
|
The Component design pattern aims to organize code into reusable, interchangeable components, promoting flexibility and ease of maintenance in game development by allowing entities to be configured with varying behaviors.
|
||||||
ease of maintenance in game development by allowing entities to be configured with varying behaviors.
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
> Suppose your video game consists of a graphics component and a sound component. Including the methods and attributes
|
> Suppose your video game consists of a graphics component and a sound component. Including the methods and attributes of both of these features in a single java class can be problematic due to many reasons. Firstly, the graphics and sound code can create an extremely long java class which can be hard to maintain. Furthermore, graphics components may be written and implemented by a separate team as to the sound contents. If both parties work simultaneously on the same java class, this may cause conflicts and major delay. Using the component design pattern, the development team is able to create individual component classes for graphics and sound whilst providing the domain/object the reach to both of these attributes.
|
||||||
> of both of these features in a single java class can be problematic due to many reasons. Firstly, the graphics and sound
|
|
||||||
> code can create an extremely long java class which can be hard to maintain. Furthermore, graphics components may be
|
|
||||||
> written and implemented by a separate team as to the sound contents. If both parties work simultaneously on the same
|
|
||||||
> java class, this may cause conflicts and major delay. Using the component design pattern, the development team is able
|
|
||||||
> to create individual component classes for graphics and sound whilst providing the domain/object the reach to both of
|
|
||||||
> these attributes.
|
|
||||||
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
> The component design pattern provides a single attribute to be accessible by numerous objects without requiring the
|
> The component design pattern provides a single attribute to be accessible by numerous objects without requiring the existence of a relationship between the objects themselves.
|
||||||
> existence of a relationship between the objects themselves.
|
|
||||||
|
|
||||||
Key drawback
|
Key drawback
|
||||||
> With the implementation of the component design pattern, it can be very difficult to create a relationship
|
> With the implementation of the component design pattern, it can be very difficult to create a relationship between components. For example, suppose we require the sound component to be aware of the current animation in order create a certain sound based upon the animation; this can be quite tricky as the component design pattern makes components 'unaware' of other components' existence due to its decoupling nature.
|
||||||
> between components. For example, suppose we require the sound component to be aware of the current animation in order
|
|
||||||
> create a certain sound based upon the animation; this can be quite tricky as the component design pattern makes
|
|
||||||
> components 'unaware' of other components' existence due to its decoupling nature.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
The App class creates a demonstration of the use of the component pattern by creating two different objects which
|
The App class creates a demonstration of the use of the component pattern by creating two different objects which inherit a small collection of individual components that are modifiable.
|
||||||
inherit a small collection of individual components that are modifiable.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public final class App {
|
public final class App {
|
||||||
@@ -68,9 +56,7 @@ public final class App {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Much of the program exists within the GameObject class, within this class, the player and NPC object create methods are
|
Much of the program exists within the GameObject class, within this class, the player and NPC object create methods are set up. Additionally, this class also consists of the method calls used to update/alter information of the object's components.
|
||||||
set up. Additionally, this class also consists of the method calls used to update/alter information of the object's
|
|
||||||
components.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class GameObject {
|
public class GameObject {
|
||||||
@@ -119,9 +105,7 @@ public class GameObject {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Upon opening the component package, the collection of components are revealed. These components provide the interface
|
Upon opening the component package, the collection of components are revealed. These components provide the interface for objects to inherit these domains. The PlayerInputComponent class shown below updates the object's velocity characteristic based on user's key event input.
|
||||||
for objects to inherit these domains. The PlayerInputComponent class shown below updates the object's velocity
|
|
||||||
characteristic based on user's key event input.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class PlayerInputComponent implements InputComponent {
|
public class PlayerInputComponent implements InputComponent {
|
||||||
@@ -159,10 +143,8 @@ public class PlayerInputComponent implements InputComponent {
|
|||||||
|
|
||||||
## Applicability
|
## Applicability
|
||||||
|
|
||||||
* Used in game development and simulations where game entities (e.g., characters, items) can have a dynamic set of
|
* Used in game development and simulations where game entities (e.g., characters, items) can have a dynamic set of abilities or states.
|
||||||
abilities or states.
|
* Suitable for systems requiring high modularity and systems where entities might need to change behavior at runtime without inheritance hierarchies.
|
||||||
* Suitable for systems requiring high modularity and systems where entities might need to change behavior at runtime
|
|
||||||
without inheritance hierarchies.
|
|
||||||
|
|
||||||
## Known Uses
|
## Known Uses
|
||||||
|
|
||||||
@@ -173,28 +155,20 @@ public class PlayerInputComponent implements InputComponent {
|
|||||||
|
|
||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* Flexibility and Reusability: Components can be reused across different entities, making it easier to add new features
|
* Flexibility and Reusability: Components can be reused across different entities, making it easier to add new features or modify existing ones.
|
||||||
or modify existing ones.
|
* Decoupling: Reduces dependencies between game entity states and behaviors, facilitating easier changes and maintenance.
|
||||||
* Decoupling: Reduces dependencies between game entity states and behaviors, facilitating easier changes and
|
* Dynamic Composition: Entities can alter their behavior at runtime by adding or removing components, providing significant flexibility in game design.
|
||||||
maintenance.
|
|
||||||
* Dynamic Composition: Entities can alter their behavior at runtime by adding or removing components, providing
|
|
||||||
significant flexibility in game design.
|
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* Complexity: Can introduce additional complexity in system architecture, particularly in managing dependencies and
|
* Complexity: Can introduce additional complexity in system architecture, particularly in managing dependencies and communications between components.
|
||||||
communications between components.
|
* Performance Considerations: Depending on implementation, may incur a performance overhead due to indirection and dynamic behavior, especially critical in high-performance game loops.
|
||||||
* Performance Considerations: Depending on implementation, may incur a performance overhead due to indirection and
|
|
||||||
dynamic behavior, especially critical in high-performance game loops.
|
|
||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
* [Decorator](https://java-design-patterns.com/patterns/decorator/): Similar concept of adding responsibilities
|
* [Decorator](https://java-design-patterns.com/patterns/decorator/): Similar concept of adding responsibilities dynamically, but without the focus on game entities.
|
||||||
dynamically, but without the focus on game entities.
|
* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Can be used in conjunction with the Component pattern to share component instances among many entities to save memory.
|
||||||
* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Can be used in conjunction with the Component
|
* [Observer](https://java-design-patterns.com/patterns/observer/): Often used in Component systems to communicate state changes between components.
|
||||||
pattern to share component instances among many entities to save memory.
|
|
||||||
* [Observer](https://java-design-patterns.com/patterns/observer/): Often used in Component systems to communicate state
|
|
||||||
changes between components.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
@@ -14,16 +14,13 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The Composite Entity design pattern is aimed at managing a set of interrelated persistent objects as if they were a
|
The Composite Entity design pattern is aimed at managing a set of interrelated persistent objects as if they were a single entity. It is commonly used in the context of Enterprise JavaBeans (EJB) and similar enterprise frameworks to represent graph-based data structures within business models, enabling clients to treat them as a single unit.
|
||||||
single entity. It is commonly used in the context of Enterprise JavaBeans (EJB) and similar enterprise frameworks to
|
|
||||||
represent graph-based data structures within business models, enabling clients to treat them as a single unit.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> For a console, there may be many interfaces that need to be managed and controlled. Using the composite entity
|
> For a console, there may be many interfaces that need to be managed and controlled. Using the composite entity pattern, dependent objects such as messages and signals can be combined and controlled using a single object.
|
||||||
> pattern, dependent objects such as messages and signals can be combined and controlled using a single object.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
@@ -31,8 +28,7 @@ In plain words
|
|||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
We need a generic solution for the problem. To achieve this, let's introduce a generic
|
We need a generic solution for the problem. To achieve this, let's introduce a generic Composite Entity Pattern.
|
||||||
Composite Entity Pattern.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public abstract class DependentObject<T> {
|
public abstract class DependentObject<T> {
|
||||||
@@ -122,8 +118,7 @@ var console=new CompositeEntity();
|
|||||||
## Applicability
|
## Applicability
|
||||||
|
|
||||||
* Useful in enterprise applications where business objects are complex and involve various interdependent objects.
|
* Useful in enterprise applications where business objects are complex and involve various interdependent objects.
|
||||||
* Ideal for scenarios where clients need to work with a unified interface to a set of objects rather than individual
|
* Ideal for scenarios where clients need to work with a unified interface to a set of objects rather than individual entities.
|
||||||
entities.
|
|
||||||
* Applicable in systems that require a simplified view of a complex data model for external clients or services.
|
* Applicable in systems that require a simplified view of a complex data model for external clients or services.
|
||||||
|
|
||||||
## Known Uses
|
## Known Uses
|
||||||
@@ -137,8 +132,7 @@ var console=new CompositeEntity();
|
|||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* Simplifies client interactions with complex entity models by providing a unified interface.
|
* Simplifies client interactions with complex entity models by providing a unified interface.
|
||||||
* Enhances reusability and maintainability of the business layer by decoupling client code from the complex internals of
|
* Enhances reusability and maintainability of the business layer by decoupling client code from the complex internals of business entities.
|
||||||
business entities.
|
|
||||||
* Facilitates easier transaction management and consistency enforcement across a set of related objects.
|
* Facilitates easier transaction management and consistency enforcement across a set of related objects.
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
@@ -149,12 +143,9 @@ Trade-offs:
|
|||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
* [Decorator](https://java-design-patterns.com/patterns/decorator/): For dynamically adding behavior to individual
|
* [Decorator](https://java-design-patterns.com/patterns/decorator/): For dynamically adding behavior to individual objects within the composite entity without affecting the structure.
|
||||||
objects within the composite entity without affecting the structure.
|
* [Facade](https://java-design-patterns.com/patterns/facade/): Provides a simplified interface to a complex subsystem, similar to how a composite entity simplifies access to a set of objects.
|
||||||
* [Facade](https://java-design-patterns.com/patterns/facade/): Provides a simplified interface to a complex subsystem,
|
* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Useful for managing shared objects within a composite entity to reduce memory footprint.
|
||||||
similar to how a composite entity simplifies access to a set of objects.
|
|
||||||
* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Useful for managing shared objects within a
|
|
||||||
composite entity to reduce memory footprint.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+29
-66
@@ -9,39 +9,27 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
The primary goal of the Composite View design pattern is to compose objects into tree structures to represent part-whole
|
The primary goal of the Composite View design pattern is to compose objects into tree structures to represent part-whole hierarchies. This allows clients to treat individual objects and compositions of objects uniformly, simplifying the management of complex structures.
|
||||||
hierarchies. This allows clients to treat individual objects and compositions of objects uniformly, simplifying the
|
|
||||||
management of complex structures.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real World Example
|
Real World Example
|
||||||
|
|
||||||
> A news site wants to display the current date and news to different users
|
> A news site wants to display the current date and news to different users based on that user's preferences. The news site will substitute in different news feed components depending on the user's interest, defaulting to local news.
|
||||||
> based on that user's preferences. The news site will substitute in different news feed
|
|
||||||
> components depending on the user's interest, defaulting to local news.
|
|
||||||
|
|
||||||
In Plain Words
|
In Plain Words
|
||||||
|
|
||||||
> Composite View Pattern is having a main view being composed of smaller subviews.
|
> Composite View Pattern is having a main view being composed of smaller subviews. The layout of this composite view is based on a template. A View-manager then decides which subviews to include in this template.
|
||||||
> The layout of this composite view is based on a template. A View-manager then decides which
|
|
||||||
> subviews to include in this template.
|
|
||||||
|
|
||||||
Wikipedia Says
|
Wikipedia Says
|
||||||
|
|
||||||
> Composite views that are composed of multiple atomic subviews. Each component of
|
> Composite views that are composed of multiple atomic subviews. Each component of the template may be included dynamically into the whole and the layout of the page may be managed independently of the content. This solution provides for the creation of a composite view based on the inclusion and substitution of modular dynamic and static template fragments. It promotes the reuse of atomic portions of the view by encouraging modular design.
|
||||||
> the template may be included dynamically into the whole and the layout of the page may be managed independently of the
|
|
||||||
> content.
|
|
||||||
> This solution provides for the creation of a composite view based on the inclusion and substitution of
|
|
||||||
> modular dynamic and static template fragments.
|
|
||||||
> It promotes the reuse of atomic portions of the view by encouraging modular design.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
Since this is a web development pattern, a server is required to demonstrate it.
|
Since this is a web development pattern, a server is required to demonstrate it. This example uses Tomcat 10.0.13 to run the servlet, and this programmatic example will only work with Tomcat 10+.
|
||||||
This example uses Tomcat 10.0.13 to run the servlet, and this programmatic example will only work with Tomcat 10+.
|
|
||||||
|
|
||||||
Firstly there is `AppServlet` which is an `HttpServlet` that runs on Tomcat 10+.
|
Firstly, there is `AppServlet` which is an `HttpServlet` that runs on Tomcat 10+.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class AppServlet extends HttpServlet {
|
public class AppServlet extends HttpServlet {
|
||||||
@@ -95,8 +83,7 @@ public class AppServlet extends HttpServlet {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This servlet is not part of the pattern, and simply forwards GET requests to the correct JSP.
|
This servlet is not part of the pattern, and simply forwards GET requests to the correct JSP. PUT, POST, and DELETE requests are not supported and will simply show an error message.
|
||||||
PUT, POST, and DELETE requests are not supported and will simply show an error message.
|
|
||||||
|
|
||||||
The view management in this example is done via a javabean class: `ClientPropertiesBean`, which stores user preferences.
|
The view management in this example is done via a javabean class: `ClientPropertiesBean`, which stores user preferences.
|
||||||
|
|
||||||
@@ -141,8 +128,8 @@ public class ClientPropertiesBean implements Serializable {
|
|||||||
```
|
```
|
||||||
|
|
||||||
This javabean has a default constructor, and another that takes an `HttpServletRequest`.
|
This javabean has a default constructor, and another that takes an `HttpServletRequest`.
|
||||||
This second constructor takes the request object, parses out the request parameters which contain the
|
|
||||||
user preferences for different types of news.
|
This second constructor takes the request object, parses out the request parameters which contain the user preferences for different types of news.
|
||||||
|
|
||||||
The template for the news page is in `newsDisplay.jsp`
|
The template for the news page is in `newsDisplay.jsp`
|
||||||
|
|
||||||
@@ -223,14 +210,11 @@ The template for the news page is in `newsDisplay.jsp`
|
|||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
This JSP page is the template. It declares a table with three rows, with one component in the first row,
|
This JSP page is the template. It declares a table with three rows, with one component in the first row, two components in the second row, and one component in the third row.
|
||||||
two components in the second row, and one component in the third row.
|
|
||||||
|
|
||||||
The scriplets in the file are part of the
|
The scriplets in the file are part of the view management strategy that include different atomic subviews based on the user preferences in the Javabean.
|
||||||
view management strategy that include different atomic subviews based on the user preferences in the Javabean.
|
|
||||||
|
|
||||||
Here are two examples of the mock atomic subviews used in the composite:
|
Here are two examples of the mock atomic subviews used in the composite: `businessNews.jsp`
|
||||||
`businessNews.jsp`
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
|
|
||||||
@@ -303,37 +287,26 @@ Here are two examples of the mock atomic subviews used in the composite:
|
|||||||
|
|
||||||
The results are as such:
|
The results are as such:
|
||||||
|
|
||||||
1) The user has put their name as `Tammy` in the request parameters and no preferences:
|
1) The user has put their name as `Tammy` in the request parameters and no preferences: 
|
||||||

|
2) The user has put their name as `Johnny` in the request parameters and has a preference for world, business, and science news: 
|
||||||
2) The user has put their name as `Johnny` in the request parameters and has a preference for world, business, and
|
|
||||||
science news:
|
|
||||||

|
|
||||||
|
|
||||||
The different subviews such as `worldNews.jsp`, `businessNews.jsp`, etc. are included conditionally
|
The different subviews such as `worldNews.jsp`, `businessNews.jsp`, etc. are included conditionally based on the request parameters.
|
||||||
based on the request parameters.
|
|
||||||
|
|
||||||
**How To Use**
|
**How To Use**
|
||||||
|
|
||||||
To try this example, make sure you have Tomcat 10+ installed.
|
To try this example, make sure you have Tomcat 10+ installed. Set up your IDE to build a WAR file from the module and deploy that file to the server
|
||||||
Set up your IDE to build a WAR file from the module and deploy that file to the server
|
|
||||||
|
|
||||||
IntelliJ:
|
IntelliJ:
|
||||||
|
|
||||||
Under `Run` and `edit configurations` Make sure Tomcat server is one of the run configurations.
|
Under `Run` and `edit configurations` Make sure Tomcat server is one of the run configurations. Go to the deployment tab, and make sure there is one artifact being built called `composite-view:war exploded`. If not present, add one.
|
||||||
Go to the deployment tab, and make sure there is one artifact being built called `composite-view:war exploded`.
|
|
||||||
If not present, add one.
|
|
||||||
|
|
||||||
Ensure that the artifact is being built from the content of the `web` directory and the compilation results of the
|
Ensure that the artifact is being built from the content of the `web` directory and the compilation results of the module. Point the output of the artifact to a convenient place. Run the configuration and view the landing page, follow instructions on that page to continue.
|
||||||
module.
|
|
||||||
Point the output of the artifact to a convenient place. Run the configuration and view the landing page,
|
|
||||||
follow instructions on that page to continue.
|
|
||||||
|
|
||||||
## Class diagram
|
## Class diagram
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The class diagram here displays the Javabean which is the view manager.
|
The class diagram here displays the Javabean which is the view manager. The views are JSP's held inside the web directory.
|
||||||
The views are JSP's held inside the web directory.
|
|
||||||
|
|
||||||
## Applicability:
|
## Applicability:
|
||||||
|
|
||||||
@@ -341,40 +314,30 @@ Use the Composite View design pattern when:
|
|||||||
|
|
||||||
* You want to represent part-whole hierarchies of objects.
|
* You want to represent part-whole hierarchies of objects.
|
||||||
* You expect that the composite structures might include any new components in the future.
|
* You expect that the composite structures might include any new components in the future.
|
||||||
* You want clients to be able to ignore the difference between compositions of objects and individual objects. Clients
|
* You want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly.
|
||||||
will treat all objects in the composite structure uniformly.
|
|
||||||
|
|
||||||
## Known Uses
|
## Known Uses
|
||||||
|
|
||||||
* Graphical User Interfaces (GUIs) where widgets can contain other widgets (e.g., a window containing panels, buttons,
|
* Graphical User Interfaces (GUIs) where widgets can contain other widgets (e.g., a window containing panels, buttons, and text fields).
|
||||||
and text fields).
|
* Document structures, such as the representation of tables containing rows, which in turn contain cells, all of which can be treated as elements in a unified hierarchy.
|
||||||
* Document structures, such as the representation of tables containing rows, which in turn contain cells, all of which
|
|
||||||
can be treated as elements in a unified hierarchy.
|
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* High flexibility in adding new components: Since composites and leaf nodes are treated uniformly, it's easier to add
|
* High flexibility in adding new components: Since composites and leaf nodes are treated uniformly, it's easier to add new kinds of components.
|
||||||
new kinds of components.
|
* Simplified client code: Clients can treat composite structures and individual elements uniformly, reducing the complexity in client code.
|
||||||
* Simplified client code: Clients can treat composite structures and individual elements uniformly, reducing the
|
|
||||||
complexity in client code.
|
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* Overgeneralization: Designing the system might become more complex if you make everything composite, especially if
|
* Overgeneralization: Designing the system might become more complex if you make everything composite, especially if your application doesn't require it.
|
||||||
your application doesn't require it.
|
* Difficulty in constraint enforcement: It can be harder to restrict the components of a composite to only certain types.
|
||||||
* Difficulty in constraint enforcement: It can be harder to restrict the components of a composite to only certain
|
|
||||||
types.
|
|
||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
* [Decorator](https://java-design-patterns.com/patterns/decorator/): While Decorator is used to add responsibilities to
|
* [Decorator](https://java-design-patterns.com/patterns/decorator/): While Decorator is used to add responsibilities to objects, Composite is meant for building structures of objects.
|
||||||
objects, Composite is meant for building structures of objects.
|
* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Composite can often be combined with Flyweight to implement shared leaf nodes in a composite structure, reducing the memory footprint.
|
||||||
* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Composite can often be combined with Flyweight to
|
* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Can be used with Composite to let components pass requests through the hierarchy.
|
||||||
implement shared leaf nodes in a composite structure, reducing the memory footprint.
|
|
||||||
* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Can be used with
|
|
||||||
Composite to let components pass requests through the hierarchy.
|
|
||||||
* [Composite](https://java-design-patterns.com/patterns/composite/)
|
* [Composite](https://java-design-patterns.com/patterns/composite/)
|
||||||
* [View Helper](https://www.oracle.com/java/technologies/viewhelper.html)
|
* [View Helper](https://www.oracle.com/java/technologies/viewhelper.html)
|
||||||
|
|
||||||
|
|||||||
+9
-23
@@ -15,16 +15,13 @@ tag:
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients
|
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
|
||||||
treat individual objects and compositions of objects uniformly.
|
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real-world example
|
Real-world example
|
||||||
|
|
||||||
> Every sentence is composed of words which are in turn composed of characters. Each of these
|
> Every sentence is composed of words which are in turn composed of characters. Each of these objects are printable and they can have something printed before or after them like sentence always ends with full stop and word always has space before it.
|
||||||
> objects are printable and they can have something printed before or after them like sentence
|
|
||||||
> always ends with full stop and word always has space before it.
|
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
@@ -32,16 +29,11 @@ In plain words
|
|||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
> In software engineering, the composite pattern is a partitioning design pattern. The composite
|
> In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes that a group of objects is to be treated in the same way as a single instance of an object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.
|
||||||
> pattern describes that a group of objects is to be treated in the same way as a single instance of
|
|
||||||
> an object. The intent of a composite is to "compose" objects into tree structures to represent
|
|
||||||
> part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects
|
|
||||||
> and compositions uniformly.
|
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
Taking our sentence example from above. Here we have the base class `LetterComposite` and the
|
Taking our sentence example from above. Here we have the base class `LetterComposite` and the different printable types `Letter`, `Word` and `Sentence`.
|
||||||
different printable types `Letter`, `Word` and `Sentence`.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public abstract class LetterComposite {
|
public abstract class LetterComposite {
|
||||||
@@ -185,20 +177,15 @@ Message from the elves:
|
|||||||
Use the Composite pattern when
|
Use the Composite pattern when
|
||||||
|
|
||||||
* You want to represent part-whole hierarchies of objects.
|
* You want to represent part-whole hierarchies of objects.
|
||||||
* You want clients to be able to ignore the difference between compositions of objects and
|
* You want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly.
|
||||||
individual objects. Clients will treat all objects in the composite structure uniformly.
|
|
||||||
|
|
||||||
## Known uses
|
## Known uses
|
||||||
|
|
||||||
* Graphical user interfaces where components can contain other components (e.g., panels containing buttons, labels,
|
* Graphical user interfaces where components can contain other components (e.g., panels containing buttons, labels, other panels).
|
||||||
other panels).
|
|
||||||
* File system representations where directories can contain files and other directories.
|
* File system representations where directories can contain files and other directories.
|
||||||
* Organizational structures where a department can contain sub-departments and employees.
|
* Organizational structures where a department can contain sub-departments and employees.
|
||||||
* [java.awt.Container](http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html)
|
* [java.awt.Container](http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html) and [java.awt.Component](http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html)
|
||||||
and [java.awt.Component](http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html)
|
* [Apache Wicket](https://github.com/apache/wicket) component tree, see [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java) and [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)
|
||||||
* [Apache Wicket](https://github.com/apache/wicket) component tree,
|
|
||||||
see [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java)
|
|
||||||
and [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)
|
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
@@ -214,8 +201,7 @@ Trade-offs:
|
|||||||
|
|
||||||
## Related Patterns
|
## Related Patterns
|
||||||
|
|
||||||
* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Composite can use Flyweight to share component
|
* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Composite can use Flyweight to share component instances among several composites.
|
||||||
instances among several composites.
|
|
||||||
* [Iterator](https://java-design-patterns.com/patterns/iterator/): Can be used to traverse Composite structures.
|
* [Iterator](https://java-design-patterns.com/patterns/iterator/): Can be used to traverse Composite structures.
|
||||||
* [Visitor](https://java-design-patterns.com/patterns/visitor/): Can apply an operation over a Composite structure.
|
* [Visitor](https://java-design-patterns.com/patterns/visitor/): Can apply an operation over a Composite structure.
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user