Compare commits
24 Commits
master
...
grammatica
Author | SHA1 | Date | |
---|---|---|---|
|
dafc57d622 | ||
|
d327918b13 | ||
|
5b0f4a9697 | ||
|
808df54dc0 | ||
|
b014dc2f00 | ||
|
9a2c5aa9aa | ||
|
ebcc857664 | ||
|
11efae38f2 | ||
|
bbc2a9ddb1 | ||
|
2b7cc410b0 | ||
|
a403c84add | ||
|
86362e12f6 | ||
|
1f6833986e | ||
|
3b1f82a2a4 | ||
|
6feca5bd01 | ||
|
588b106ada | ||
|
0d41af972d | ||
|
57783aa341 | ||
|
abc8e0d88a | ||
|
26c06d8f7f | ||
|
ed98e7a128 | ||
|
0f9f3b90c2 | ||
|
e361223def | ||
|
7a46174391 |
@ -196,13 +196,13 @@ Example use cases
|
||||
* Unit test case writing becomes much easier
|
||||
* UI tools for different OS
|
||||
|
||||
## Consequences:
|
||||
## Consequences
|
||||
|
||||
* Dependency injection in java hides the service class dependencies that can lead to runtime errors that would have been caught at compile time.
|
||||
* While the pattern is great when creating predefined objects, adding the new ones might be challenging.
|
||||
* The code becomes more complicated than it should be since a lot of new interfaces and classes are introduced along with the pattern.
|
||||
|
||||
## Tutorial
|
||||
## Tutorials
|
||||
|
||||
* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java)
|
||||
|
||||
|
@ -105,7 +105,7 @@ Use the Adapter pattern when
|
||||
* you need to use several existing subclasses, but it's impractical to adapt their interface by subclassing every one. An object adapter can adapt the interface of its parent class.
|
||||
* most of the applications using third party libraries use adapters as a middle layer between the application and the 3rd party library to decouple the application from the library. If another library has to be used only an adapter for the new library is required without having to change the application code.
|
||||
|
||||
## Consequences:
|
||||
## Consequences
|
||||
Class and object adapters have different trade-offs. A class adapter
|
||||
|
||||
* adapts Adaptee to Target by committing to a concrete Adaptee class. As a consequence, a class adapter won’t work when we want to adapt a class and all its subclasses.
|
||||
@ -118,7 +118,7 @@ An object adapter
|
||||
* makes it harder to override Adaptee behavior. It will require subclassing Adaptee and making Adapter refer to the subclass rather than the Adaptee itself.
|
||||
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)
|
||||
* [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)
|
||||
|
@ -19,7 +19,7 @@ Decouple an abstraction from its implementation so that the two can vary indepen
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> Consider you have a weapon with different enchantments, and you are supposed to allow mixing
|
||||
> different weapons with different enchantments. What would you do? Create multiple copies of each
|
||||
@ -161,27 +161,36 @@ public class SoulEatingEnchantment implements Enchantment {
|
||||
Here are both hierarchies in action:
|
||||
|
||||
```java
|
||||
LOGGER.info("The knight receives an enchanted sword.");
|
||||
var enchantedSword = new Sword(new SoulEatingEnchantment());
|
||||
enchantedSword.wield();
|
||||
enchantedSword.swing();
|
||||
enchantedSword.unwield();
|
||||
// The sword is wielded.
|
||||
// The item spreads bloodlust.
|
||||
// The sword is swinged.
|
||||
// The item eats the soul of enemies.
|
||||
// The sword is unwielded.
|
||||
// Bloodlust slowly disappears.
|
||||
|
||||
LOGGER.info("The valkyrie receives an enchanted hammer.");
|
||||
var hammer = new Hammer(new FlyingEnchantment());
|
||||
hammer.wield();
|
||||
hammer.swing();
|
||||
hammer.unwield();
|
||||
// The hammer is wielded.
|
||||
// The item begins to glow faintly.
|
||||
// The hammer is swinged.
|
||||
// The item flies and strikes the enemies finally returning to owner's hand.
|
||||
// The hammer is unwielded.
|
||||
// The item's glow fades.
|
||||
```
|
||||
|
||||
Here's the console output.
|
||||
|
||||
```
|
||||
The knight receives an enchanted sword.
|
||||
The sword is wielded.
|
||||
The item spreads bloodlust.
|
||||
The sword is swung.
|
||||
The item eats the soul of enemies.
|
||||
The sword is unwielded.
|
||||
Bloodlust slowly disappears.
|
||||
The valkyrie receives an enchanted hammer.
|
||||
The hammer is wielded.
|
||||
The item begins to glow faintly.
|
||||
The hammer is swung.
|
||||
The item flies and strikes the enemies finally returning to owner's hand.
|
||||
The hammer is unwielded.
|
||||
The item's glow fades.
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
|
@ -16,11 +16,11 @@ process can create different representations.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> Imagine a character generator for a role-playing game. The easiest option is to let the computer
|
||||
> create the character for you. If you want to manually select the character details like
|
||||
> profession, gender, hair color etc. the character generation becomes a step-by-step process that
|
||||
> profession, gender, hair color, etc. the character generation becomes a step-by-step process that
|
||||
> completes when all the selections are ready.
|
||||
|
||||
In plain words
|
||||
@ -49,7 +49,7 @@ anti-pattern.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
The sane alternative is to use the Builder pattern. First of all we have our hero that we want to
|
||||
The sane alternative is to use the Builder pattern. First of all, we have our hero that we want to
|
||||
create:
|
||||
|
||||
```java
|
||||
@ -134,7 +134,7 @@ Use the Builder pattern when
|
||||
* The algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled
|
||||
* The construction process must allow different representations for the object that's constructed
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)
|
||||
* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) as well as similar buffers such as FloatBuffer, IntBuffer and so on.
|
||||
|
@ -1,8 +1,8 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Chain of responsibility
|
||||
folder: chain
|
||||
permalink: /patterns/chain/
|
||||
folder: chain-of-responsibility
|
||||
permalink: /patterns/chain-of-responsibility/
|
||||
categories: Behavioral
|
||||
language: en
|
||||
tags:
|
||||
@ -10,16 +10,17 @@ tags:
|
||||
---
|
||||
|
||||
## Intent
|
||||
|
||||
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to
|
||||
handle the request. Chain the receiving objects and pass the request along the chain until an object
|
||||
handles it.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> The Orc King gives loud orders to his army. The closest one to react is the commander, then
|
||||
> officer and then soldier. The commander, officer and soldier here form a chain of responsibility.
|
||||
> an officer, and then a soldier. The commander, officer, and soldier form a chain of responsibility.
|
||||
|
||||
In plain words
|
||||
|
||||
@ -35,7 +36,7 @@ Wikipedia says
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
Translating our example with the orcs from above. First we have the `Request` class:
|
||||
Translating our example with the orcs from above. First, we have the `Request` class:
|
||||
|
||||
```java
|
||||
public class Request {
|
||||
@ -66,7 +67,7 @@ public enum RequestType {
|
||||
}
|
||||
```
|
||||
|
||||
Then the request handler hierarchy
|
||||
Next, we show the request handler hierarchy.
|
||||
|
||||
```java
|
||||
@Slf4j
|
||||
@ -116,7 +117,7 @@ public class OrcCommander extends RequestHandler {
|
||||
|
||||
```
|
||||
|
||||
Then we have the Orc King who gives the orders and forms the chain
|
||||
The Orc King gives the orders and forms the chain.
|
||||
|
||||
```java
|
||||
public class OrcKing {
|
||||
@ -136,18 +137,26 @@ public class OrcKing {
|
||||
}
|
||||
```
|
||||
|
||||
Then it is used as follows
|
||||
The chain of responsibility in action.
|
||||
|
||||
```java
|
||||
var king = new OrcKing();
|
||||
king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); // Orc commander handling request "defend castle"
|
||||
king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner")); // Orc officer handling request "torture prisoner"
|
||||
king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); // Orc soldier handling request "collect tax"
|
||||
king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle"));
|
||||
king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner"));
|
||||
king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax"));
|
||||
```
|
||||
|
||||
The console output.
|
||||
|
||||
```
|
||||
Orc commander handling request "defend castle"
|
||||
Orc officer handling request "torture prisoner"
|
||||
Orc soldier handling request "collect tax"
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
@ -157,7 +166,7 @@ Use Chain of Responsibility when
|
||||
* You want to issue a request to one of several objects without specifying the receiver explicitly.
|
||||
* The set of objects that can handle a request should be specified dynamically.
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29)
|
||||
* [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html)
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
@ -31,7 +31,7 @@
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.25.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>chain</artifactId>
|
||||
<artifactId>chain-of-responsibility</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
@ -1,4 +1,4 @@
|
||||
---
|
||||
---
|
||||
layout: pattern
|
||||
title: Command
|
||||
folder: command
|
||||
@ -19,7 +19,7 @@ Encapsulate a request as an object, thereby letting you parameterize clients wit
|
||||
requests, queue or log requests, and support undoable operations.
|
||||
|
||||
## Explanation
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> There is a wizard casting spells on a goblin. The spells are executed on the goblin one by one.
|
||||
> The first spell shrinks the goblin and the second makes him invisible. Then the wizard reverses
|
||||
@ -135,7 +135,7 @@ public class Goblin extends Target {
|
||||
}
|
||||
```
|
||||
|
||||
Finally we have the wizard in main function who casts spell
|
||||
Finally, we have the wizard in the main function casting spells.
|
||||
|
||||
```java
|
||||
public static void main(String[] args) {
|
||||
@ -202,32 +202,29 @@ Use the Command pattern when you want to:
|
||||
* Parameterize objects by an action to perform. You can express such parameterization in a
|
||||
procedural language with a callback function, that is, a function that's registered somewhere to be
|
||||
called at a later point. Commands are an object-oriented replacement for callbacks.
|
||||
* Specify, queue, and execute requests at different times. A Command object can have a lifetime
|
||||
* Specify, queue, and execute requests at different times. A Command object can have a life
|
||||
independent of the original request. If the receiver of a request can be represented in an address
|
||||
space-independent way, then you can transfer a command object for the request to a different process
|
||||
and fulfill the request there.
|
||||
* Support undo. The Command's execute operation can store state for reversing its effects in the
|
||||
command itself. The Command interface must have an added un-execute operation that reverses the
|
||||
effects of a previous call to execute. The executed commands are stored in a history list.
|
||||
Unlimited-level undo and redo is achieved by traversing this list backwards and forwards calling
|
||||
un-execute and execute, respectively.
|
||||
Unlimited-level undo and redo functionality is achieved by traversing this list backward and forward
|
||||
calling un-execute and execute, respectively.
|
||||
* Support logging changes so that they can be reapplied in case of a system crash. By augmenting the
|
||||
Command interface with load and store operations, you can keep a persistent log of changes.
|
||||
Recovering from a crash involves reloading logged commands from disk and re-executing them with
|
||||
Recovering from a crash involves reloading logged commands from the disk and re-executing them with
|
||||
the execute operation.
|
||||
* Structure a system around high-level operations build on primitive operations. Such a structure is
|
||||
common in information systems that support transactions. A transaction encapsulates a set of changes
|
||||
to data. The Command pattern offers a way to model transactions. Commands have a common interface,
|
||||
common in information systems that support transactions. A transaction encapsulates a set of data
|
||||
changes. The Command pattern offers a way to model transactions. Commands have a common interface,
|
||||
letting you invoke all transactions the same way. The pattern also makes it easy to extend the
|
||||
system with new transactions.
|
||||
* Keep a history of requests.
|
||||
* Implement callback functionality.
|
||||
* Implement the undo functionality.
|
||||
|
||||
## Typical Use Case
|
||||
|
||||
* To keep a history of requests
|
||||
* Implement callback functionality
|
||||
* Implement the undo functionality
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)
|
||||
* [org.junit.runners.model.Statement](https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/runners/model/Statement.java)
|
||||
|
@ -26,7 +26,7 @@ package com.iluwatar.command;
|
||||
/**
|
||||
* The Command pattern is a behavioral design pattern in which an object is used to encapsulate all
|
||||
* information needed to perform an action or trigger an event at a later time. This information
|
||||
* includes the method name, the object that owns the method and values for the method parameters.
|
||||
* includes the method name, the object that owns the method, and values for the method parameters.
|
||||
*
|
||||
* <p>Four terms always associated with the command pattern are command, receiver, invoker and
|
||||
* client. A command object (spell) knows about the receiver (target) and invokes a method of the
|
||||
|
@ -16,15 +16,15 @@ treat individual objects and compositions of objects uniformly.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> Every sentence is composed of words which are in turn composed of characters. Each of these
|
||||
> objects is printable and they can have something printed before or after them like sentence always
|
||||
> ends with full stop and word always has space before it.
|
||||
> objects are printable and they can have something printed before or after them like sentence
|
||||
> always ends with full stop and word always has space before it.
|
||||
|
||||
In plain words
|
||||
|
||||
> Composite pattern lets clients treat the individual objects in a uniform manner.
|
||||
> Composite pattern lets clients uniformly treat the individual objects.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
@ -154,10 +154,22 @@ public class Messenger {
|
||||
And then it can be used as:
|
||||
|
||||
```java
|
||||
var orcMessage = new Messenger().messageFromOrcs();
|
||||
orcMessage.print(); // Where there is a whip there is a way.
|
||||
var elfMessage = new Messenger().messageFromElves();
|
||||
elfMessage.print(); // Much wind pours from your mouth.
|
||||
var messenger = new Messenger();
|
||||
|
||||
LOGGER.info("Message from the orcs: ");
|
||||
messenger.messageFromOrcs().print();
|
||||
|
||||
LOGGER.info("Message from the elves: ");
|
||||
messenger.messageFromElves().print();
|
||||
```
|
||||
|
||||
The console output:
|
||||
|
||||
```
|
||||
Message from the orcs:
|
||||
Where there is a whip there is a way.
|
||||
Message from the elves:
|
||||
Much wind pours from your mouth.
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
@ -172,7 +184,7 @@ Use the Composite pattern when
|
||||
* You want clients to be able to ignore the difference between compositions of objects and
|
||||
individual objects. Clients will treat all objects in the composite structure uniformly.
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.awt.Container](http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html) and [java.awt.Component](http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html)
|
||||
* [Apache Wicket](https://github.com/apache/wicket) component tree, see [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java) and [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)
|
||||
|
@ -45,14 +45,13 @@ public class App {
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
var messenger = new Messenger();
|
||||
|
||||
LOGGER.info("Message from the orcs: ");
|
||||
messenger.messageFromOrcs().print();
|
||||
|
||||
var orcMessage = new Messenger().messageFromOrcs();
|
||||
orcMessage.print();
|
||||
|
||||
LOGGER.info("\nMessage from the elves: ");
|
||||
|
||||
var elfMessage = new Messenger().messageFromElves();
|
||||
elfMessage.print();
|
||||
LOGGER.info("Message from the elves: ");
|
||||
messenger.messageFromElves().print();
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,6 @@ public class Sentence extends LetterComposite {
|
||||
|
||||
@Override
|
||||
protected void printThisAfter() {
|
||||
System.out.print(".");
|
||||
System.out.print(".\n");
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ permalink: /patterns/decorator/
|
||||
categories: Structural
|
||||
language: en
|
||||
tags:
|
||||
- Gang Of Four
|
||||
- Gang of Four
|
||||
- Extensibility
|
||||
---
|
||||
|
||||
@ -21,9 +21,9 @@ alternative to subclassing for extending functionality.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> There is an angry troll living in the nearby hills. Usually it goes bare handed but sometimes it
|
||||
> There is an angry troll living in the nearby hills. Usually, it goes bare-handed but sometimes it
|
||||
> has a weapon. To arm the troll it's not necessary to create a new troll but to decorate it
|
||||
> dynamically with a suitable weapon.
|
||||
|
||||
@ -72,7 +72,7 @@ public class SimpleTroll implements Troll {
|
||||
}
|
||||
```
|
||||
|
||||
Next we want to add club for the troll. We can do it dynamically by using a decorator:
|
||||
Next, we want to add a club for the troll. We can do it dynamically by using a decorator:
|
||||
|
||||
```java
|
||||
@Slf4j
|
||||
@ -106,23 +106,33 @@ Here's the troll in action:
|
||||
|
||||
```java
|
||||
// simple troll
|
||||
LOGGER.info("A simple looking troll approaches.");
|
||||
var troll = new SimpleTroll();
|
||||
troll.attack(); // The troll tries to grab you!
|
||||
troll.fleeBattle(); // The troll shrieks in horror and runs away!
|
||||
troll.attack();
|
||||
troll.fleeBattle();
|
||||
LOGGER.info("Simple troll power: {}.\n", troll.getAttackPower());
|
||||
|
||||
// change the behavior of the simple troll by adding a decorator
|
||||
LOGGER.info("A troll with huge club surprises you.");
|
||||
var clubbedTroll = new ClubbedTroll(troll);
|
||||
clubbedTroll.attack(); // The troll tries to grab you! The troll swings at you with a club!
|
||||
clubbedTroll.fleeBattle(); // The troll shrieks in horror and runs away!
|
||||
clubbedTroll.attack();
|
||||
clubbedTroll.fleeBattle();
|
||||
LOGGER.info("Clubbed troll power: {}.\n", clubbedTroll.getAttackPower());
|
||||
```
|
||||
|
||||
Program output:
|
||||
|
||||
```java
|
||||
A simple looking troll approaches.
|
||||
The troll tries to grab you!
|
||||
The troll shrieks in horror and runs away!
|
||||
The troll tries to grab you! The troll swings at you with a club!
|
||||
Simple troll power: 10.
|
||||
|
||||
A troll with huge club surprises you.
|
||||
The troll tries to grab you!
|
||||
The troll swings at you with a club!
|
||||
The troll shrieks in horror and runs away!
|
||||
Clubbed troll power: 20.
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
@ -140,11 +150,11 @@ affecting other objects.
|
||||
are possible and would produce an explosion of subclasses to support every combination. Or a class
|
||||
definition may be hidden or otherwise unavailable for subclassing.
|
||||
|
||||
## Tutorial
|
||||
## Tutorials
|
||||
|
||||
* [Decorator Pattern Tutorial](https://www.journaldev.com/1540/decorator-design-pattern-in-java-example)
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.io.InputStream](http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html), [java.io.OutputStream](http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html),
|
||||
[java.io.Reader](http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html) and [java.io.Writer](http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html)
|
||||
|
@ -50,13 +50,13 @@ public class App {
|
||||
var troll = new SimpleTroll();
|
||||
troll.attack();
|
||||
troll.fleeBattle();
|
||||
LOGGER.info("Simple troll power {}.\n", troll.getAttackPower());
|
||||
LOGGER.info("Simple troll power: {}.\n", troll.getAttackPower());
|
||||
|
||||
// change the behavior of the simple troll by adding a decorator
|
||||
LOGGER.info("A troll with huge club surprises you.");
|
||||
var clubbedTroll = new ClubbedTroll(troll);
|
||||
clubbedTroll.attack();
|
||||
clubbedTroll.fleeBattle();
|
||||
LOGGER.info("Clubbed troll power {}.\n", clubbedTroll.getAttackPower());
|
||||
LOGGER.info("Clubbed troll power: {}.\n", clubbedTroll.getAttackPower());
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ interface that makes the subsystem easier to use.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> How does a goldmine work? "Well, the miners go down there and dig gold!" you say. That is what you
|
||||
> believe because you are using a simple interface that goldmine provides on the outside, internally
|
||||
|
@ -7,7 +7,7 @@ categories: Creational
|
||||
language: en
|
||||
tags:
|
||||
- Extensibility
|
||||
- Gang Of Four
|
||||
- Gang of Four
|
||||
---
|
||||
|
||||
## Also known as
|
||||
@ -21,7 +21,7 @@ Factory Method lets a class defer instantiation to subclasses.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> Blacksmith manufactures weapons. Elves require Elvish weapons and orcs require Orcish weapons.
|
||||
> Depending on the customer at hand the right type of blacksmith is summoned.
|
||||
@ -40,7 +40,7 @@ Wikipedia says
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
Taking our blacksmith example above. First of all we have a `Blacksmith` interface and some
|
||||
Taking our blacksmith example above. First of all, we have a `Blacksmith` interface and some
|
||||
implementations for it:
|
||||
|
||||
```java
|
||||
@ -65,15 +65,25 @@ When the customers come, the correct type of blacksmith is summoned and requeste
|
||||
manufactured:
|
||||
|
||||
```java
|
||||
var blacksmith = new ElfBlacksmith();
|
||||
blacksmith.manufactureWeapon(WeaponType.SPEAR);
|
||||
blacksmith.manufactureWeapon(WeaponType.AXE);
|
||||
Blacksmith blacksmith = new OrcBlacksmith();
|
||||
Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
|
||||
LOGGER.info("{} manufactured {}", blacksmith, weapon);
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
|
||||
LOGGER.info("{} manufactured {}", blacksmith, weapon);
|
||||
|
||||
blacksmith = new ElfBlacksmith();
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
|
||||
LOGGER.info("{} manufactured {}", blacksmith, weapon);
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
|
||||
LOGGER.info("{} manufactured {}", blacksmith, weapon);
|
||||
```
|
||||
|
||||
Program output:
|
||||
```java
|
||||
// Elven spear
|
||||
// Elven axe
|
||||
```
|
||||
The orc blacksmith manufactured an orcish spear
|
||||
The orc blacksmith manufactured an orcish axe
|
||||
The elf blacksmith manufactured an elven spear
|
||||
The elf blacksmith manufactured an elven axe
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
@ -89,7 +99,7 @@ Use the Factory Method pattern when:
|
||||
* Classes delegate responsibility to one of several helper subclasses, and you want to localize the
|
||||
knowledge of which helper subclass is the delegate.
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.util.Calendar](http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)
|
||||
* [java.util.ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)
|
||||
|
@ -26,7 +26,7 @@ package com.iluwatar.factory.method;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* The Factory Method is a creational design pattern which uses factory methods to deal with the
|
||||
* The Factory Method is a creational design pattern that uses factory methods to deal with the
|
||||
* problem of creating objects without specifying the exact class of object that will be created.
|
||||
* This is done by creating objects via calling a factory method either specified in an interface
|
||||
* and implemented by child classes, or implemented in a base class and optionally overridden by
|
||||
@ -41,39 +41,22 @@ import lombok.extern.slf4j.Slf4j;
|
||||
@Slf4j
|
||||
public class App {
|
||||
|
||||
private final Blacksmith blacksmith;
|
||||
|
||||
/**
|
||||
* Creates an instance of <code>App</code> which will use <code>blacksmith</code> to manufacture
|
||||
* the weapons for war.
|
||||
* <code>App</code> is unaware which concrete implementation of {@link Blacksmith} it is using.
|
||||
* The decision of which blacksmith implementation to use may depend on configuration, or
|
||||
* the type of rival in war.
|
||||
* @param blacksmith a non-null implementation of blacksmith
|
||||
*/
|
||||
public App(Blacksmith blacksmith) {
|
||||
this.blacksmith = blacksmith;
|
||||
}
|
||||
|
||||
/**
|
||||
* Program entry point.
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// Lets go to war with Orc weapons
|
||||
var app = new App(new OrcBlacksmith());
|
||||
app.manufactureWeapons();
|
||||
|
||||
// Lets go to war with Elf weapons
|
||||
app = new App(new ElfBlacksmith());
|
||||
app.manufactureWeapons();
|
||||
}
|
||||
|
||||
private void manufactureWeapons() {
|
||||
var weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
|
||||
LOGGER.info(weapon.toString());
|
||||
Blacksmith blacksmith = new OrcBlacksmith();
|
||||
Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
|
||||
LOGGER.info("{} manufactured {}", blacksmith, weapon);
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
|
||||
LOGGER.info(weapon.toString());
|
||||
LOGGER.info("{} manufactured {}", blacksmith, weapon);
|
||||
|
||||
blacksmith = new ElfBlacksmith();
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
|
||||
LOGGER.info("{} manufactured {}", blacksmith, weapon);
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
|
||||
LOGGER.info("{} manufactured {}", blacksmith, weapon);
|
||||
}
|
||||
}
|
||||
|
@ -44,4 +44,8 @@ public class ElfBlacksmith implements Blacksmith {
|
||||
return ELFARSENAL.get(weaponType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "The elf blacksmith";
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,6 @@ public class ElfWeapon implements Weapon {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Elven " + weaponType;
|
||||
return "an elven " + weaponType;
|
||||
}
|
||||
}
|
||||
|
@ -43,4 +43,9 @@ public class OrcBlacksmith implements Blacksmith {
|
||||
public Weapon manufactureWeapon(WeaponType weaponType) {
|
||||
return ORCARSENAL.get(weaponType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "The orc blacksmith";
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,6 @@ public class OrcWeapon implements Weapon {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Orcish " + weaponType;
|
||||
return "an orcish " + weaponType;
|
||||
}
|
||||
}
|
||||
|
@ -16,16 +16,17 @@ tags:
|
||||
|
||||
## Intent
|
||||
|
||||
Providing a static method encapsulated in a class called factory, in order to hide the
|
||||
implementation logic and makes client code focus on usage rather then initialization new objects.
|
||||
Providing a static method encapsulated in a class called the factory, to hide the implementation
|
||||
logic and make client code focus on usage rather than initializing new objects.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> Lets say we have a web application connected to SQLServer, but now we want to switch to Oracle. To
|
||||
> do so without modifying existing source code, we need to implements Simple Factory pattern, in
|
||||
> which a static method can be invoked to create connection to a given database.
|
||||
> Imagine an alchemist who is about to manufacture coins. The alchemist must be able to create both
|
||||
> gold and copper coins and switching between them must be possible without modifying the existing
|
||||
> source code. The factory pattern makes it possible by providing a static construction method which
|
||||
> can be called with relevant parameters.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
@ -34,16 +35,16 @@ Wikipedia says
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
We have an interface `Car` and two implementations `Ford` and `Ferrari`.
|
||||
We have an interface `Coin` and two implementations `GoldCoin` and `CopperCoin`.
|
||||
|
||||
```java
|
||||
public interface Car {
|
||||
public interface Coin {
|
||||
String getDescription();
|
||||
}
|
||||
|
||||
public class Ford implements Car {
|
||||
public class GoldCoin implements Coin {
|
||||
|
||||
static final String DESCRIPTION = "This is Ford.";
|
||||
static final String DESCRIPTION = "This is a gold coin.";
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
@ -51,9 +52,9 @@ public class Ford implements Car {
|
||||
}
|
||||
}
|
||||
|
||||
public class Ferrari implements Car {
|
||||
public class CopperCoin implements Coin {
|
||||
|
||||
static final String DESCRIPTION = "This is Ferrari.";
|
||||
static final String DESCRIPTION = "This is a copper coin.";
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
@ -62,51 +63,48 @@ public class Ferrari implements Car {
|
||||
}
|
||||
```
|
||||
|
||||
Enumeration above represents types of cars that we support (`Ford` and `Ferrari`).
|
||||
Enumeration above represents types of coins that we support (`GoldCoin` and `CopperCoin`).
|
||||
|
||||
```java
|
||||
public enum CarType {
|
||||
|
||||
FORD(Ford::new),
|
||||
FERRARI(Ferrari::new);
|
||||
|
||||
private final Supplier<Car> constructor;
|
||||
|
||||
CarType(Supplier<Car> constructor) {
|
||||
this.constructor = constructor;
|
||||
}
|
||||
|
||||
public Supplier<Car> getConstructor() {
|
||||
return this.constructor;
|
||||
}
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum CoinType {
|
||||
|
||||
COPPER(CopperCoin::new),
|
||||
GOLD(GoldCoin::new);
|
||||
|
||||
private final Supplier<Coin> constructor;
|
||||
}
|
||||
```
|
||||
Then we have the static method `getCar` to create car objects encapsulated in the factory class
|
||||
`CarsFactory`.
|
||||
|
||||
Then we have the static method `getCoin` to create coin objects encapsulated in the factory class
|
||||
`CoinFactory`.
|
||||
|
||||
```java
|
||||
public class CarsFactory {
|
||||
|
||||
public static Car getCar(CarType type) {
|
||||
public class CoinFactory {
|
||||
|
||||
public static Coin getCoin(CoinType type) {
|
||||
return type.getConstructor().get();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now on the client code we can create different types of cars using the factory class.
|
||||
Now on the client code we can create different types of coins using the factory class.
|
||||
|
||||
```java
|
||||
var car1 = CarsFactory.getCar(CarType.FORD);
|
||||
var car2 = CarsFactory.getCar(CarType.FERRARI);
|
||||
LOGGER.info(car1.getDescription());
|
||||
LOGGER.info(car2.getDescription());
|
||||
LOGGER.info("The alchemist begins his work.");
|
||||
var coin1 = CoinFactory.getCoin(CoinType.COPPER);
|
||||
var coin2 = CoinFactory.getCoin(CoinType.GOLD);
|
||||
LOGGER.info(coin1.getDescription());
|
||||
LOGGER.info(coin2.getDescription());
|
||||
```
|
||||
|
||||
Program output:
|
||||
|
||||
```java
|
||||
This is Ford.
|
||||
This is Ferrari.
|
||||
The alchemist begins his work.
|
||||
This is a copper coin.
|
||||
This is a gold coin.
|
||||
```
|
||||
|
||||
## Class Diagram
|
||||
@ -115,7 +113,7 @@ This is Ferrari.
|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Simple Factory pattern when you only care about the creation of a object, not how to create
|
||||
Use the factory pattern when you only care about the creation of a object, not how to create
|
||||
and manage it.
|
||||
|
||||
Pros
|
||||
@ -127,13 +125,13 @@ Cons
|
||||
|
||||
* The code becomes more complicated than it should be.
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.util.Calendar#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)
|
||||
* [java.util.ResourceBundle#getBundle()](https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)
|
||||
* [java.text.NumberFormat#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)
|
||||
* [java.nio.charset.Charset#forName()](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)
|
||||
* [java.net.URLStreamHandlerFactory#createURLStreamHandler(String)](https://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html) (Returns different singleton objects, depending on a protocol)
|
||||
* [java.net.URLStreamHandlerFactory#createURLStreamHandler(String)](https://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html) (returns different singleton objects, depending on a protocol)
|
||||
* [java.util.EnumSet#of()](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of(E))
|
||||
* [javax.xml.bind.JAXBContext#createMarshaller()](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--) and other similar methods.
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 29 KiB |
@ -5,31 +5,32 @@ package com.iluwatar.factory {
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
interface Car {
|
||||
interface Coin {
|
||||
+ getDescription() : String {abstract}
|
||||
}
|
||||
class CarsFactory {
|
||||
+ CarsFactory()
|
||||
+ getCar(type : CarType) : Car {static}
|
||||
class CoinFactory {
|
||||
+ CoinFactory()
|
||||
+ getCoin(type : CoinType) : Coin {static}
|
||||
}
|
||||
~enum CarType {
|
||||
+ FERRARI {static}
|
||||
+ FORD {static}
|
||||
+ valueOf(name : String) : CarType {static}
|
||||
+ values() : CarType[] {static}
|
||||
enum CoinType {
|
||||
+ COPPER {static}
|
||||
+ GOLD {static}
|
||||
- constructor : Supplier<Coin>
|
||||
+ getConstructor() : Supplier<Coin>
|
||||
+ valueOf(name : String) : CoinType {static}
|
||||
+ values() : CoinType[] {static}
|
||||
}
|
||||
class Ferrari {
|
||||
class CopperCoin {
|
||||
~ DESCRIPTION : String {static}
|
||||
+ Ferrari()
|
||||
+ CopperCoin()
|
||||
+ getDescription() : String
|
||||
}
|
||||
class Ford {
|
||||
class GoldCoin {
|
||||
~ DESCRIPTION : String {static}
|
||||
+ Ford()
|
||||
+ GoldCoin()
|
||||
+ getDescription() : String
|
||||
}
|
||||
}
|
||||
CarType ..+ CarsFactory
|
||||
Ferrari ..|> Car
|
||||
Ford ..|> Car
|
||||
CopperCoin ..|> Coin
|
||||
GoldCoin ..|> Coin
|
||||
@enduml
|
@ -30,8 +30,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
* create and return objects of varying classes, in order to hide the implementation logic
|
||||
* and makes client code focus on usage rather then objects initialization and management.
|
||||
*
|
||||
* <p>In this example the CarFactory is the factory class and it provides a static method to
|
||||
* create different cars.
|
||||
* <p>In this example an alchemist manufactures coins. CoinFactory is the factory class and it
|
||||
* provides a static method to create different types of coins.
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@ -41,9 +41,10 @@ public class App {
|
||||
* Program main entry point.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
var car1 = CarsFactory.getCar(CarType.FORD);
|
||||
var car2 = CarsFactory.getCar(CarType.FERRARI);
|
||||
LOGGER.info(car1.getDescription());
|
||||
LOGGER.info(car2.getDescription());
|
||||
LOGGER.info("The alchemist begins his work.");
|
||||
var coin1 = CoinFactory.getCoin(CoinType.COPPER);
|
||||
var coin2 = CoinFactory.getCoin(CoinType.GOLD);
|
||||
LOGGER.info(coin1.getDescription());
|
||||
LOGGER.info(coin2.getDescription());
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,9 @@
|
||||
package com.iluwatar.factory;
|
||||
|
||||
/**
|
||||
* Car interface.
|
||||
* Coin interface.
|
||||
*/
|
||||
public interface Car {
|
||||
public interface Coin {
|
||||
|
||||
String getDescription();
|
||||
|
@ -24,14 +24,14 @@
|
||||
package com.iluwatar.factory;
|
||||
|
||||
/**
|
||||
* Factory of cars.
|
||||
* Factory of coins.
|
||||
*/
|
||||
public class CarsFactory {
|
||||
public class CoinFactory {
|
||||
|
||||
/**
|
||||
* Factory method takes as parameter a car type and initiate the appropriate class.
|
||||
* Factory method takes as a parameter the coin type and calls the appropriate class.
|
||||
*/
|
||||
public static Car getCar(CarType type) {
|
||||
public static Coin getCoin(CoinType type) {
|
||||
return type.getConstructor().get();
|
||||
}
|
||||
}
|
@ -28,15 +28,14 @@ import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* Enumeration for different types of cars.
|
||||
* Enumeration for different types of coins.
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum CarType {
|
||||
public enum CoinType {
|
||||
|
||||
FORD(Ford::new),
|
||||
FERRARI(Ferrari::new);
|
||||
|
||||
private final Supplier<Car> constructor;
|
||||
COPPER(CopperCoin::new),
|
||||
GOLD(GoldCoin::new);
|
||||
|
||||
private final Supplier<Coin> constructor;
|
||||
}
|
@ -24,11 +24,11 @@
|
||||
package com.iluwatar.factory;
|
||||
|
||||
/**
|
||||
* Ferrari implementation.
|
||||
* CopperCoin implementation.
|
||||
*/
|
||||
public class Ferrari implements Car {
|
||||
public class CopperCoin implements Coin {
|
||||
|
||||
static final String DESCRIPTION = "This is Ferrari.";
|
||||
static final String DESCRIPTION = "This is a copper coin.";
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
@ -24,11 +24,11 @@
|
||||
package com.iluwatar.factory;
|
||||
|
||||
/**
|
||||
* Ford implementation.
|
||||
* GoldCoin implementation.
|
||||
*/
|
||||
public class Ford implements Car {
|
||||
public class GoldCoin implements Coin {
|
||||
|
||||
static final String DESCRIPTION = "This is Ford.";
|
||||
static final String DESCRIPTION = "This is a gold coin.";
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
@ -27,12 +27,11 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class CarsFactoryTest {
|
||||
class CoinFactoryTest {
|
||||
|
||||
@Test
|
||||
void shouldReturnFerrariInstance() {
|
||||
final var ferrari = CarsFactory.getCar(CarType.FERRARI);
|
||||
assertTrue(ferrari instanceof Ferrari);
|
||||
void shouldReturnGoldCoinInstance() {
|
||||
final var goldCoin = CoinFactory.getCoin(CoinType.GOLD);
|
||||
assertTrue(goldCoin instanceof GoldCoin);
|
||||
}
|
||||
|
||||
}
|
@ -6,7 +6,7 @@ permalink: /patterns/flyweight/
|
||||
categories: Structural
|
||||
language: en
|
||||
tags:
|
||||
- Gang Of Four
|
||||
- Gang of Four
|
||||
- Performance
|
||||
---
|
||||
|
||||
@ -16,11 +16,11 @@ Use sharing to support large numbers of fine-grained objects efficiently.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> Alchemist's shop has shelves full of magic potions. Many of the potions are the same so there is
|
||||
> no need to create new object for each of them. Instead one object instance can represent multiple
|
||||
> shelf items so memory footprint remains small.
|
||||
> no need to create a new object for each of them. Instead, one object instance can represent
|
||||
> multiple shelf items so the memory footprint remains small.
|
||||
|
||||
In plain words
|
||||
|
||||
@ -36,7 +36,7 @@ Wikipedia says
|
||||
|
||||
**Programmatic example**
|
||||
|
||||
Translating our alchemist shop example from above. First of all we have different potion types:
|
||||
Translating our alchemist shop example from above. First of all, we have different potion types:
|
||||
|
||||
```java
|
||||
public interface Potion {
|
||||
@ -104,27 +104,81 @@ public class PotionFactory {
|
||||
}
|
||||
```
|
||||
|
||||
And it can be used as below:
|
||||
`AlchemistShop` contains two shelves of magic potions. The potions are created using the
|
||||
aforementioned `PotionFactory`.
|
||||
|
||||
```java
|
||||
var factory = new PotionFactory();
|
||||
factory.createPotion(PotionType.INVISIBILITY).drink(); // You become invisible. (Potion=6566818)
|
||||
factory.createPotion(PotionType.HEALING).drink(); // You feel healed. (Potion=648129364)
|
||||
factory.createPotion(PotionType.INVISIBILITY).drink(); // You become invisible. (Potion=6566818)
|
||||
factory.createPotion(PotionType.HOLY_WATER).drink(); // You feel blessed. (Potion=1104106489)
|
||||
factory.createPotion(PotionType.HOLY_WATER).drink(); // You feel blessed. (Potion=1104106489)
|
||||
factory.createPotion(PotionType.HEALING).drink(); // You feel healed. (Potion=648129364)
|
||||
@Slf4j
|
||||
public class AlchemistShop {
|
||||
|
||||
private final List<Potion> topShelf;
|
||||
private final List<Potion> bottomShelf;
|
||||
|
||||
public AlchemistShop() {
|
||||
var factory = new PotionFactory();
|
||||
topShelf = List.of(
|
||||
factory.createPotion(PotionType.INVISIBILITY),
|
||||
factory.createPotion(PotionType.INVISIBILITY),
|
||||
factory.createPotion(PotionType.STRENGTH),
|
||||
factory.createPotion(PotionType.HEALING),
|
||||
factory.createPotion(PotionType.INVISIBILITY),
|
||||
factory.createPotion(PotionType.STRENGTH),
|
||||
factory.createPotion(PotionType.HEALING),
|
||||
factory.createPotion(PotionType.HEALING)
|
||||
);
|
||||
bottomShelf = List.of(
|
||||
factory.createPotion(PotionType.POISON),
|
||||
factory.createPotion(PotionType.POISON),
|
||||
factory.createPotion(PotionType.POISON),
|
||||
factory.createPotion(PotionType.HOLY_WATER),
|
||||
factory.createPotion(PotionType.HOLY_WATER)
|
||||
);
|
||||
}
|
||||
|
||||
public final List<Potion> getTopShelf() {
|
||||
return List.copyOf(this.topShelf);
|
||||
}
|
||||
|
||||
public final List<Potion> getBottomShelf() {
|
||||
return List.copyOf(this.bottomShelf);
|
||||
}
|
||||
|
||||
public void drinkPotions() {
|
||||
LOGGER.info("Drinking top shelf potions\n");
|
||||
topShelf.forEach(Potion::drink);
|
||||
LOGGER.info("Drinking bottom shelf potions\n");
|
||||
bottomShelf.forEach(Potion::drink);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In our scenario, a brave visitor enters the alchemist shop and drinks all the potions.
|
||||
|
||||
```java
|
||||
// create the alchemist shop with the potions
|
||||
var alchemistShop = new AlchemistShop();
|
||||
// a brave visitor enters the alchemist shop and drinks all the potions
|
||||
alchemistShop.drinkPotions();
|
||||
```
|
||||
|
||||
Program output:
|
||||
|
||||
```java
|
||||
You become invisible. (Potion=6566818)
|
||||
You feel healed. (Potion=648129364)
|
||||
You become invisible. (Potion=6566818)
|
||||
You feel blessed. (Potion=1104106489)
|
||||
You feel blessed. (Potion=1104106489)
|
||||
You feel healed. (Potion=648129364)
|
||||
Drinking top shelf potions
|
||||
You become invisible. (Potion=1509514333)
|
||||
You become invisible. (Potion=1509514333)
|
||||
You feel strong. (Potion=739498517)
|
||||
You feel healed. (Potion=125130493)
|
||||
You become invisible. (Potion=1509514333)
|
||||
You feel strong. (Potion=739498517)
|
||||
You feel healed. (Potion=125130493)
|
||||
You feel healed. (Potion=125130493)
|
||||
Drinking bottom shelf potions
|
||||
Urgh! This is poisonous. (Potion=166239592)
|
||||
Urgh! This is poisonous. (Potion=166239592)
|
||||
Urgh! This is poisonous. (Potion=166239592)
|
||||
You feel blessed. (Potion=991505714)
|
||||
You feel blessed. (Potion=991505714)
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
@ -138,13 +192,13 @@ Flyweight pattern when all of the following are true:
|
||||
|
||||
* An application uses a large number of objects.
|
||||
* Storage costs are high because of the sheer quantity of objects.
|
||||
* Most object state can be made extrinsic.
|
||||
* Many groups of objects may be replaced by relatively few shared objects once extrinsic state is
|
||||
removed.
|
||||
* Most of the object state can be made extrinsic.
|
||||
* Many groups of objects may be replaced by relatively few shared objects once the extrinsic state
|
||||
is removed.
|
||||
* The application doesn't depend on object identity. Since flyweight objects may be shared, identity
|
||||
tests will return true for conceptually distinct objects.
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.lang.Integer#valueOf(int)](http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#valueOf%28int%29) and similarly for Byte, Character and other wrapped types.
|
||||
|
||||
|
@ -78,12 +78,12 @@ public class AlchemistShop {
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerate potions.
|
||||
* Drink all the potions.
|
||||
*/
|
||||
public void enumerate() {
|
||||
LOGGER.info("Enumerating top shelf potions\n");
|
||||
public void drinkPotions() {
|
||||
LOGGER.info("Drinking top shelf potions");
|
||||
topShelf.forEach(Potion::drink);
|
||||
LOGGER.info("Enumerating bottom shelf potions\n");
|
||||
LOGGER.info("Drinking bottom shelf potions");
|
||||
bottomShelf.forEach(Potion::drink);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,9 @@ public class App {
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// create the alchemist shop with the potions
|
||||
var alchemistShop = new AlchemistShop();
|
||||
alchemistShop.enumerate();
|
||||
// a brave visitor enters the alchemist shop and drinks all the potions
|
||||
alchemistShop.drinkPotions();
|
||||
}
|
||||
}
|
||||
|
@ -10,22 +10,161 @@ tags:
|
||||
---
|
||||
|
||||
## Intent
|
||||
Given a language, define a representation for its grammar along
|
||||
with an interpreter that uses the representation to interpret sentences in the
|
||||
language.
|
||||
|
||||
Given a language, define a representation for its grammar along with an interpreter that uses the
|
||||
representation to interpret sentences in the language.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real-world example
|
||||
|
||||
> The halfling kids are learning basic math at school. They start from the very basics "1 + 1",
|
||||
> "4 - 2", "5 + 5", and so forth.
|
||||
|
||||
In plain words
|
||||
|
||||
> Interpreter pattern interprets sentences in the desired language.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> In computer programming, the interpreter pattern is a design pattern that specifies how to
|
||||
> evaluate sentences in a language. The basic idea is to have a class for each symbol (terminal or
|
||||
> nonterminal) in a specialized computer language. The syntax tree of a sentence in the language
|
||||
> is an instance of the composite pattern and is used to evaluate (interpret) the sentence for
|
||||
> a client.
|
||||
|
||||
**Programmatic example**
|
||||
|
||||
To be able to interpret basic math, we need a hierarchy of expressions. The basic abstraction for
|
||||
it is the `Expression` class.
|
||||
|
||||
```java
|
||||
public abstract class Expression {
|
||||
|
||||
public abstract int interpret();
|
||||
|
||||
@Override
|
||||
public abstract String toString();
|
||||
}
|
||||
```
|
||||
|
||||
The simplest of the expressions is the `NumberExpression` that contains only a single integer
|
||||
number.
|
||||
|
||||
```java
|
||||
public class NumberExpression extends Expression {
|
||||
|
||||
private final int number;
|
||||
|
||||
public NumberExpression(int number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public NumberExpression(String s) {
|
||||
this.number = Integer.parseInt(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int interpret() {
|
||||
return number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "number";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The more complex expressions are operations such as `PlusExpression`, `MinusExpression`, and
|
||||
`MultiplyExpression`. Here's the first of them, the others are similar.
|
||||
|
||||
```java
|
||||
public class PlusExpression extends Expression {
|
||||
|
||||
private final Expression leftExpression;
|
||||
private final Expression rightExpression;
|
||||
|
||||
public PlusExpression(Expression leftExpression, Expression rightExpression) {
|
||||
this.leftExpression = leftExpression;
|
||||
this.rightExpression = rightExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int interpret() {
|
||||
return leftExpression.interpret() + rightExpression.interpret();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "+";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now we are able to show the interpreter pattern in action parsing some simple math.
|
||||
|
||||
```java
|
||||
// the halfling kids are learning some basic math at school
|
||||
// define the math string we want to parse
|
||||
final var tokenString = "4 3 2 - 1 + *";
|
||||
|
||||
// the stack holds the parsed expressions
|
||||
var stack = new Stack<Expression>();
|
||||
|
||||
// tokenize the string and go through them one by one
|
||||
var tokenList = tokenString.split(" ");
|
||||
for (var s : tokenList) {
|
||||
if (isOperator(s)) {
|
||||
// when an operator is encountered we expect that the numbers can be popped from the top of
|
||||
// the stack
|
||||
var rightExpression = stack.pop();
|
||||
var leftExpression = stack.pop();
|
||||
LOGGER.info("popped from stack left: {} right: {}",
|
||||
leftExpression.interpret(), rightExpression.interpret());
|
||||
var operator = getOperatorInstance(s, leftExpression, rightExpression);
|
||||
LOGGER.info("operator: {}", operator);
|
||||
var result = operator.interpret();
|
||||
// the operation result is pushed on top of the stack
|
||||
var resultExpression = new NumberExpression(result);
|
||||
stack.push(resultExpression);
|
||||
LOGGER.info("push result to stack: {}", resultExpression.interpret());
|
||||
} else {
|
||||
// numbers are pushed on top of the stack
|
||||
var i = new NumberExpression(s);
|
||||
stack.push(i);
|
||||
LOGGER.info("push to stack: {}", i.interpret());
|
||||
}
|
||||
}
|
||||
// in the end, the final result lies on top of the stack
|
||||
LOGGER.info("result: {}", stack.pop().interpret());
|
||||
```
|
||||
|
||||
Executing the program produces the following console output.
|
||||
|
||||
```
|
||||
popped from stack left: 1 right: 1
|
||||
operator: +
|
||||
push result to stack: 2
|
||||
popped from stack left: 4 right: 2
|
||||
operator: *
|
||||
push result to stack: 8
|
||||
result: 8
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
Use the Interpreter pattern when there is a language to
|
||||
interpret, and you can represent statements in the language as abstract syntax
|
||||
trees. The Interpreter pattern works best when
|
||||
|
||||
* the grammar is simple. For complex grammars, the class hierarchy for the grammar becomes large and unmanageable. Tools such as parser generators are a better alternative in such cases. They can interpret expressions without building abstract syntax trees, which can save space and possibly time
|
||||
* efficiency is not a critical concern. The most efficient interpreters are usually not implemented by interpreting parse trees directly but by first translating them into another form. For example, regular expressions are often transformed into state machines. But even then, the translator can be implemented by the Interpreter pattern, so the pattern is still applicable
|
||||
Use the Interpreter pattern when there is a language to interpret, and you can represent statements
|
||||
in the language as abstract syntax trees. The Interpreter pattern works best when
|
||||
|
||||
## Real world examples
|
||||
* The grammar is simple. For complex grammars, the class hierarchy for the grammar becomes large and unmanageable. Tools such as parser generators are a better alternative in such cases. They can interpret expressions without building abstract syntax trees, which can save space and possibly time
|
||||
* Efficiency is not a critical concern. The most efficient interpreters are usually not implemented by interpreting parse trees directly but by first translating them into another form. For example, regular expressions are often transformed into state machines. But even then, the translator can be implemented by the Interpreter pattern, so the pattern is still applicable
|
||||
|
||||
## Known uses
|
||||
|
||||
* [java.util.Pattern](http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html)
|
||||
* [java.text.Normalizer](http://docs.oracle.com/javase/8/docs/api/java/text/Normalizer.html)
|
||||
|
@ -34,25 +34,33 @@ import lombok.extern.slf4j.Slf4j;
|
||||
*
|
||||
* <p>In this example we use the Interpreter pattern to break sentences into expressions ({@link
|
||||
* Expression}) that can be evaluated and as a whole form the result.
|
||||
*
|
||||
* <p>Expressions can be evaluated using prefix, infix or postfix notations This sample uses
|
||||
* postfix, where operator comes after the operands.
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point.
|
||||
*
|
||||
* <p>Expressions can be evaluated using prefix, infix or postfix notations This sample uses
|
||||
* postfix, where operator comes after the operands.
|
||||
*
|
||||
* @param args command line args
|
||||
* @param args program arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
var tokenString = "4 3 2 - 1 + *";
|
||||
|
||||
// the halfling kids are learning some basic math at school
|
||||
// define the math string we want to parse
|
||||
final var tokenString = "4 3 2 - 1 + *";
|
||||
|
||||
// the stack holds the parsed expressions
|
||||
var stack = new Stack<Expression>();
|
||||
|
||||
// tokenize the string and go through them one by one
|
||||
var tokenList = tokenString.split(" ");
|
||||
for (var s : tokenList) {
|
||||
if (isOperator(s)) {
|
||||
// when an operator is encountered we expect that the numbers can be popped from the top of
|
||||
// the stack
|
||||
var rightExpression = stack.pop();
|
||||
var leftExpression = stack.pop();
|
||||
LOGGER.info("popped from stack left: {} right: {}",
|
||||
@ -60,24 +68,36 @@ public class App {
|
||||
var operator = getOperatorInstance(s, leftExpression, rightExpression);
|
||||
LOGGER.info("operator: {}", operator);
|
||||
var result = operator.interpret();
|
||||
// the operation result is pushed on top of the stack
|
||||
var resultExpression = new NumberExpression(result);
|
||||
stack.push(resultExpression);
|
||||
LOGGER.info("push result to stack: {}", resultExpression.interpret());
|
||||
} else {
|
||||
// numbers are pushed on top of the stack
|
||||
var i = new NumberExpression(s);
|
||||
stack.push(i);
|
||||
LOGGER.info("push to stack: {}", i.interpret());
|
||||
}
|
||||
}
|
||||
// in the end, the final result lies on top of the stack
|
||||
LOGGER.info("result: {}", stack.pop().interpret());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the input parameter is an operator.
|
||||
* @param s input string
|
||||
* @return true if the input parameter is an operator
|
||||
*/
|
||||
public static boolean isOperator(String s) {
|
||||
return s.equals("+") || s.equals("-") || s.equals("*");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get expression for string.
|
||||
* Returns correct expression based on the parameters.
|
||||
* @param s input string
|
||||
* @param left expression
|
||||
* @param right expression
|
||||
* @return expression
|
||||
*/
|
||||
public static Expression getOperatorInstance(String s, Expression left, Expression right) {
|
||||
switch (s) {
|
||||
@ -85,8 +105,6 @@ public class App {
|
||||
return new PlusExpression(left, right);
|
||||
case "-":
|
||||
return new MinusExpression(left, right);
|
||||
case "*":
|
||||
return new MultiplyExpression(left, right);
|
||||
default:
|
||||
return new MultiplyExpression(left, right);
|
||||
}
|
||||
|
@ -19,10 +19,10 @@ underlying representation.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> Treasure chest contains a set of magical items. There multiple types of items such as rings,
|
||||
> potions and weapons. The items can be browsed by type using an iterator the treasure chest
|
||||
> potions, and weapons. The items can be browsed by type using an iterator the treasure chest
|
||||
> provides.
|
||||
|
||||
In plain words
|
||||
@ -113,7 +113,7 @@ public interface Iterator<T> {
|
||||
}
|
||||
```
|
||||
|
||||
In the following example we iterate through the ring type items found in the chest.
|
||||
In the following example, we iterate through the ring-type items found in the chest.
|
||||
|
||||
```java
|
||||
var itemIterator = TREASURE_CHEST.iterator(ItemType.RING);
|
||||
@ -145,7 +145,7 @@ Use the Iterator pattern
|
||||
|
||||
* [How to Use Iterator?](http://www.tutorialspoint.com/java/java_using_iterator.htm)
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.util.Iterator](http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html)
|
||||
* [java.util.Enumeration](http://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html)
|
||||
|
@ -11,21 +11,192 @@ tags:
|
||||
---
|
||||
|
||||
## Intent
|
||||
Define an object that encapsulates how a set of objects interact.
|
||||
Mediator promotes loose coupling by keeping objects from referring to each
|
||||
other explicitly, and it lets you vary their interaction independently.
|
||||
|
||||
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling
|
||||
by keeping objects from referring to each other explicitly, and it lets you vary their interaction
|
||||
independently.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real-world example
|
||||
|
||||
> Rogue, wizard, hobbit, and hunter have decided to join their forces and travel in the same
|
||||
> party. To avoid coupling each member with each other, they use the party interface to
|
||||
> communicate with each other.
|
||||
|
||||
In plain words
|
||||
|
||||
> Mediator decouples a set of classes by forcing their communications flow through a mediating
|
||||
> object.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> In software engineering, the mediator pattern defines an object that encapsulates how a set of
|
||||
> objects interact. This pattern is considered to be a behavioral pattern due to the way it can
|
||||
> alter the program's running behavior. In object-oriented programming, programs often consist of
|
||||
> many classes. Business logic and computation are distributed among these classes. However, as
|
||||
> more classes are added to a program, especially during maintenance and/or refactoring, the
|
||||
> problem of communication between these classes may become more complex. This makes the program
|
||||
> harder to read and maintain. Furthermore, it can become difficult to change the program, since
|
||||
> any change may affect code in several other classes. With the mediator pattern, communication
|
||||
> between objects is encapsulated within a mediator object. Objects no longer communicate directly
|
||||
> with each other, but instead communicate through the mediator. This reduces the dependencies
|
||||
> between communicating objects, thereby reducing coupling.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
In this example, the mediator encapsulates how a set of objects interact. Instead of referring to
|
||||
each other directly they use the mediator interface.
|
||||
|
||||
The party members `Rogue`, `Wizard`, `Hobbit`, and `Hunter` all inherit from the `PartyMemberBase`
|
||||
implementing the `PartyMember` interface.
|
||||
|
||||
```java
|
||||
public interface PartyMember {
|
||||
|
||||
void joinedParty(Party party);
|
||||
|
||||
void partyAction(Action action);
|
||||
|
||||
void act(Action action);
|
||||
}
|
||||
|
||||
@Slf4j
|
||||
public abstract class PartyMemberBase implements PartyMember {
|
||||
|
||||
protected Party party;
|
||||
|
||||
@Override
|
||||
public void joinedParty(Party party) {
|
||||
LOGGER.info("{} joins the party", this);
|
||||
this.party = party;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partyAction(Action action) {
|
||||
LOGGER.info("{} {}", this, action.getDescription());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(Action action) {
|
||||
if (party != null) {
|
||||
LOGGER.info("{} {}", this, action);
|
||||
party.act(this, action);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract String toString();
|
||||
}
|
||||
|
||||
public class Rogue extends PartyMemberBase {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Rogue";
|
||||
}
|
||||
}
|
||||
|
||||
// Wizard, Hobbit, and Hunter are implemented similarly
|
||||
```
|
||||
|
||||
Our mediator system consists of `Party` interface and its implementation.
|
||||
|
||||
```java
|
||||
public interface Party {
|
||||
|
||||
void addMember(PartyMember member);
|
||||
|
||||
void act(PartyMember actor, Action action);
|
||||
}
|
||||
|
||||
public class PartyImpl implements Party {
|
||||
|
||||
private final List<PartyMember> members;
|
||||
|
||||
public PartyImpl() {
|
||||
members = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(PartyMember actor, Action action) {
|
||||
for (var member : members) {
|
||||
if (!member.equals(actor)) {
|
||||
member.partyAction(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMember(PartyMember member) {
|
||||
members.add(member);
|
||||
member.joinedParty(this);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here's a demo showing the mediator pattern in action.
|
||||
|
||||
```java
|
||||
// create party and members
|
||||
Party party = new PartyImpl();
|
||||
var hobbit = new Hobbit();
|
||||
var wizard = new Wizard();
|
||||
var rogue = new Rogue();
|
||||
var hunter = new Hunter();
|
||||
|
||||
// add party members
|
||||
party.addMember(hobbit);
|
||||
party.addMember(wizard);
|
||||
party.addMember(rogue);
|
||||
party.addMember(hunter);
|
||||
|
||||
// perform actions -> the other party members
|
||||
// are notified by the party
|
||||
hobbit.act(Action.ENEMY);
|
||||
wizard.act(Action.TALE);
|
||||
rogue.act(Action.GOLD);
|
||||
hunter.act(Action.HUNT);
|
||||
```
|
||||
|
||||
Here's the console output from running the example.
|
||||
|
||||
```
|
||||
Hobbit joins the party
|
||||
Wizard joins the party
|
||||
Rogue joins the party
|
||||
Hunter joins the party
|
||||
Hobbit spotted enemies
|
||||
Wizard runs for cover
|
||||
Rogue runs for cover
|
||||
Hunter runs for cover
|
||||
Wizard tells a tale
|
||||
Hobbit comes to listen
|
||||
Rogue comes to listen
|
||||
Hunter comes to listen
|
||||
Rogue found gold
|
||||
Hobbit takes his share of the gold
|
||||
Wizard takes his share of the gold
|
||||
Hunter takes his share of the gold
|
||||
Hunter hunted a rabbit
|
||||
Hobbit arrives for dinner
|
||||
Wizard arrives for dinner
|
||||
Rogue arrives for dinner
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Mediator pattern when
|
||||
|
||||
* a set of objects communicate in well-defined but complex ways. The resulting interdependencies are unstructured and difficult to understand
|
||||
* reusing an object is difficult because it refers to and communicates with many other objects
|
||||
* a behavior that's distributed between several classes should be customizable without a lot of subclassing
|
||||
* A set of objects communicate in well-defined but complex ways. The resulting interdependencies are unstructured and difficult to understand
|
||||
* Reusing an object is difficult because it refers to and communicates with many other objects
|
||||
* A behavior that's distributed between several classes should be customizable without a lot of subclassing
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* All scheduleXXX() methods of [java.util.Timer](http://docs.oracle.com/javase/8/docs/api/java/util/Timer.html)
|
||||
* [java.util.concurrent.Executor#execute()](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-)
|
||||
|
@ -20,10 +20,10 @@ object can be restored to this state later.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> We are working on astrology application where we need to analyze star properties over time. We are
|
||||
> creating snapshots of star state using Memento pattern.
|
||||
> We are working on an astrology application where we need to analyze star properties over time. We
|
||||
> are creating snapshots of star states using the Memento pattern.
|
||||
|
||||
In plain words
|
||||
|
||||
@ -51,7 +51,7 @@ public enum StarType {
|
||||
```
|
||||
|
||||
Next, let's jump straight to the essentials. Here's the `Star` class along with the mementos that we
|
||||
need manipulate. Especially pay attention to `getMemento` and `setMemento` methods.
|
||||
need to manipulate. Especially pay attention to `getMemento` and `setMemento` methods.
|
||||
|
||||
```java
|
||||
public interface StarMemento {
|
||||
@ -176,7 +176,7 @@ Use the Memento pattern when
|
||||
* A direct interface to obtaining the state would expose implementation details and break the
|
||||
object's encapsulation
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.util.Date](http://docs.oracle.com/javase/8/docs/api/java/util/Date.html)
|
||||
|
||||
|
@ -21,10 +21,10 @@ dependents are notified and updated automatically.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> In a land far away lives the races of hobbits and orcs. Both of them are mostly outdoors so they
|
||||
> closely follow the changes in weather. One could say that they are constantly observing the
|
||||
> In a land far away live the races of hobbits and orcs. Both of them are mostly outdoors so they
|
||||
> closely follow the weather changes. One could say that they are constantly observing the
|
||||
> weather.
|
||||
|
||||
In plain words
|
||||
@ -152,11 +152,7 @@ be changed.
|
||||
* When an object should be able to notify other objects without making assumptions about who these
|
||||
objects are. In other words, you don't want these objects tightly coupled.
|
||||
|
||||
## Typical Use Case
|
||||
|
||||
* Changing in one object leads to a change in other objects.
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.util.Observer](http://docs.oracle.com/javase/8/docs/api/java/util/Observer.html)
|
||||
* [java.util.EventListener](http://docs.oracle.com/javase/8/docs/api/java/util/EventListener.html)
|
||||
|
@ -58,7 +58,7 @@ public class App {
|
||||
weather.timePasses();
|
||||
weather.timePasses();
|
||||
|
||||
// Generic observer inspired by Java Generics and Collection by Naftalin & Wadler
|
||||
// Generic observer inspired by Java Generics and Collections by Naftalin & Wadler
|
||||
LOGGER.info("--Running generic version--");
|
||||
var genericWeather = new GWeather();
|
||||
genericWeather.addObserver(new GOrcs());
|
||||
|
2
pom.xml
2
pom.xml
@ -105,7 +105,7 @@
|
||||
<module>facade</module>
|
||||
<module>flyweight</module>
|
||||
<module>proxy</module>
|
||||
<module>chain</module>
|
||||
<module>chain-of-responsibility</module>
|
||||
<module>command</module>
|
||||
<module>interpreter</module>
|
||||
<module>iterator</module>
|
||||
|
@ -17,17 +17,17 @@ copying this prototype.
|
||||
|
||||
## Explanation
|
||||
|
||||
First it should be noted that Prototype pattern is not used to gain performance benefits. It's only
|
||||
used for creating new objects from prototype instance.
|
||||
First, it should be noted that the Prototype pattern is not used to gain performance benefits. It's only
|
||||
used for creating new objects from prototype instances.
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> Remember Dolly? The sheep that was cloned! Lets not get into the details but the key point here is
|
||||
> that it is all about cloning.
|
||||
|
||||
In plain words
|
||||
|
||||
> Create object based on an existing object through cloning.
|
||||
> Create an object based on an existing object through cloning.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
@ -40,35 +40,127 @@ of going through the trouble of creating an object from scratch and setting it u
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
In Java, it can be easily done by implementing `Cloneable` and overriding `clone` from `Object`
|
||||
In Java, the prototype pattern is recommended to be implemented as follows. First, create an
|
||||
interface with a method for cloning objects. In this example, `Prototype` interface accomplishes
|
||||
this with its `copy` method.
|
||||
|
||||
```java
|
||||
class Sheep implements Cloneable {
|
||||
private String name;
|
||||
public Sheep(String name) { this.name = name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
public String getName() { return name; }
|
||||
public interface Prototype {
|
||||
Object copy();
|
||||
}
|
||||
```
|
||||
|
||||
Our example contains a hierarchy of different creatures. For example, let's look at `Beast` and
|
||||
`OrcBeast` classes.
|
||||
|
||||
```java
|
||||
@EqualsAndHashCode
|
||||
@NoArgsConstructor
|
||||
public abstract class Beast implements Prototype {
|
||||
|
||||
public Beast(Beast source) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sheep clone() {
|
||||
try {
|
||||
return (Sheep)super.clone();
|
||||
} catch(CloneNotSuportedException) {
|
||||
throw new InternalError();
|
||||
}
|
||||
public abstract Beast copy();
|
||||
}
|
||||
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@RequiredArgsConstructor
|
||||
public class OrcBeast extends Beast {
|
||||
|
||||
private final String weapon;
|
||||
|
||||
public OrcBeast(OrcBeast orcBeast) {
|
||||
super(orcBeast);
|
||||
this.weapon = orcBeast.weapon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrcBeast copy() {
|
||||
return new OrcBeast(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Orcish wolf attacks with " + weapon;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then it can be cloned like below:
|
||||
We don't want to go into too much details, but the full example contains also base classes `Mage`
|
||||
and `Warlord` and there are specialized implementations for those for elves in addition to orcs.
|
||||
|
||||
To take full advantage of the prototype pattern, we create `HeroFactory` and `HeroFactoryImpl`
|
||||
classes to produce different kinds of creatures from prototypes.
|
||||
|
||||
```java
|
||||
var original = new Sheep("Jolly");
|
||||
System.out.println(original.getName()); // Jolly
|
||||
public interface HeroFactory {
|
||||
|
||||
Mage createMage();
|
||||
Warlord createWarlord();
|
||||
Beast createBeast();
|
||||
}
|
||||
|
||||
// Clone and modify what is required
|
||||
var cloned = original.clone();
|
||||
cloned.setName("Dolly");
|
||||
System.out.println(cloned.getName()); // Dolly
|
||||
@RequiredArgsConstructor
|
||||
public class HeroFactoryImpl implements HeroFactory {
|
||||
|
||||
private final Mage mage;
|
||||
private final Warlord warlord;
|
||||
private final Beast beast;
|
||||
|
||||
public Mage createMage() {
|
||||
return mage.copy();
|
||||
}
|
||||
|
||||
public Warlord createWarlord() {
|
||||
return warlord.copy();
|
||||
}
|
||||
|
||||
public Beast createBeast() {
|
||||
return beast.copy();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now, we are able to show the full prototype pattern in action producing new creatures by cloning
|
||||
existing instances.
|
||||
|
||||
```java
|
||||
var factory = new HeroFactoryImpl(
|
||||
new ElfMage("cooking"),
|
||||
new ElfWarlord("cleaning"),
|
||||
new ElfBeast("protecting")
|
||||
);
|
||||
var mage = factory.createMage();
|
||||
var warlord = factory.createWarlord();
|
||||
var beast = factory.createBeast();
|
||||
LOGGER.info(mage.toString());
|
||||
LOGGER.info(warlord.toString());
|
||||
LOGGER.info(beast.toString());
|
||||
|
||||
factory = new HeroFactoryImpl(
|
||||
new OrcMage("axe"),
|
||||
new OrcWarlord("sword"),
|
||||
new OrcBeast("laser")
|
||||
);
|
||||
mage = factory.createMage();
|
||||
warlord = factory.createWarlord();
|
||||
beast = factory.createBeast();
|
||||
LOGGER.info(mage.toString());
|
||||
LOGGER.info(warlord.toString());
|
||||
LOGGER.info(beast.toString());
|
||||
```
|
||||
|
||||
Here's the console output from running the example.
|
||||
|
||||
```
|
||||
Elven mage helps in cooking
|
||||
Elven warlord helps in cleaning
|
||||
Elven eagle helps in protecting
|
||||
Orcish mage attacks with axe
|
||||
Orcish warlord attacks with sword
|
||||
Orcish wolf attacks with laser
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
@ -87,7 +179,7 @@ more convenient to install a corresponding number of prototypes and clone them r
|
||||
instantiating the class manually, each time with the appropriate state.
|
||||
* When object creation is expensive compared to cloning.
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.lang.Object#clone()](http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone%28%29)
|
||||
|
||||
|
@ -29,7 +29,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
* The Prototype pattern is a creational design pattern in software development. It is used when the
|
||||
* type of objects to create is determined by a prototypical instance, which is cloned to produce
|
||||
* new objects. This pattern is used to: - avoid subclasses of an object creator in the client
|
||||
* application, like the abstract factory pattern does. - avoid the inherent cost of creating a new
|
||||
* application, like the abstract factory pattern, does. - avoid the inherent cost of creating a new
|
||||
* object in the standard way (e.g., using the 'new' keyword)
|
||||
*
|
||||
* <p>In this example we have a factory class ({@link HeroFactoryImpl}) producing objects by
|
||||
|
@ -20,7 +20,7 @@ Provide a surrogate or placeholder for another object to control access to it.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> Imagine a tower where the local wizards go to study their spells. The ivory tower can only be
|
||||
> accessed through a proxy which ensures that only the first three wizards can enter. Here the proxy
|
||||
@ -142,7 +142,7 @@ applicable.
|
||||
* Protection proxy controls access to the original object. Protection proxies are useful when
|
||||
objects should have different access rights.
|
||||
|
||||
## Typical Use Case
|
||||
Typically, the proxy pattern is used to
|
||||
|
||||
* Control access to another object
|
||||
* Lazy initialization
|
||||
|
@ -13,13 +13,12 @@ tags:
|
||||
|
||||
Ensure a class only has one instance, and provide a global point of access to it.
|
||||
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> There can only be one ivory tower where the wizards study their magic. The same enchanted ivory
|
||||
> tower is always used by the wizards. Ivory tower here is singleton.
|
||||
> tower is always used by the wizards. The ivory tower here is a singleton.
|
||||
|
||||
In plain words
|
||||
|
||||
@ -46,9 +45,17 @@ public enum EnumIvoryTower {
|
||||
Then in order to use:
|
||||
|
||||
```java
|
||||
var enumIvoryTower1 = EnumIvoryTower.INSTANCE;
|
||||
var enumIvoryTower2 = EnumIvoryTower.INSTANCE;
|
||||
assertEquals(enumIvoryTower1, enumIvoryTower2); // true
|
||||
var enumIvoryTower1 = EnumIvoryTower.INSTANCE;
|
||||
var enumIvoryTower2 = EnumIvoryTower.INSTANCE;
|
||||
LOGGER.info("enumIvoryTower1={}", enumIvoryTower1);
|
||||
LOGGER.info("enumIvoryTower2={}", enumIvoryTower2);
|
||||
```
|
||||
|
||||
The console output
|
||||
|
||||
```
|
||||
enumIvoryTower1=com.iluwatar.singleton.EnumIvoryTower@1221555852
|
||||
enumIvoryTower2=com.iluwatar.singleton.EnumIvoryTower@1221555852
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
@ -62,13 +69,13 @@ Use the Singleton pattern when
|
||||
* There must be exactly one instance of a class, and it must be accessible to clients from a well-known access point
|
||||
* When the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code
|
||||
|
||||
## Typical Use Case
|
||||
Some typical use cases for the Singleton
|
||||
|
||||
* The logging class
|
||||
* Managing a connection to a database
|
||||
* File manager
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [java.lang.Runtime#getRuntime()](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime%28%29)
|
||||
* [java.awt.Desktop#getDesktop()](http://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#getDesktop--)
|
||||
@ -77,8 +84,8 @@ Use the Singleton pattern when
|
||||
|
||||
## Consequences
|
||||
|
||||
* Violates Single Responsibility Principle (SRP) by controlling their own creation and lifecycle.
|
||||
* Encourages using a global shared instance which prevents an object and resources used by this object from being deallocated.
|
||||
* Violates Single Responsibility Principle (SRP) by controlling their creation and lifecycle.
|
||||
* Encourages using a globally shared instance which prevents an object and resources used by this object from being deallocated.
|
||||
* Creates tightly coupled code. The clients of the Singleton become difficult to test.
|
||||
* Makes it almost impossible to subclass a Singleton.
|
||||
|
||||
|
@ -30,20 +30,20 @@ import lombok.extern.slf4j.Slf4j;
|
||||
* classloader instance and provides global access to it.</p>
|
||||
*
|
||||
* <p>One of the risks of this pattern is that bugs resulting from setting a singleton up in a
|
||||
* distributed environment can be tricky to debug, since it will work fine if you debug with a
|
||||
* distributed environment can be tricky to debug since it will work fine if you debug with a
|
||||
* single classloader. Additionally, these problems can crop up a while after the implementation of
|
||||
* a singleton, since they may start out synchronous and only become async with time, so it may
|
||||
* not be clear why you are seeing certain changes in behaviour.</p>
|
||||
* a singleton, since they may start synchronous and only become async with time, so it may
|
||||
* not be clear why you are seeing certain changes in behavior.</p>
|
||||
*
|
||||
* <p>There are many ways to implement the Singleton. The first one is the eagerly initialized
|
||||
* instance in {@link IvoryTower}. Eager initialization implies that the implementation is thread
|
||||
* safe. If you can afford giving up control of the instantiation moment, then this implementation
|
||||
* safe. If you can afford to give up control of the instantiation moment, then this implementation
|
||||
* will suit you fine.</p>
|
||||
*
|
||||
* <p>The other option to implement eagerly initialized Singleton is enum based Singleton. The
|
||||
* example is found in {@link EnumIvoryTower}. At first glance the code looks short and simple.
|
||||
* <p>The other option to implement eagerly initialized Singleton is enum-based Singleton. The
|
||||
* example is found in {@link EnumIvoryTower}. At first glance, the code looks short and simple.
|
||||
* However, you should be aware of the downsides including committing to implementation strategy,
|
||||
* extending the enum class, serializability and restrictions to coding. These are extensively
|
||||
* extending the enum class, serializability, and restrictions to coding. These are extensively
|
||||
* discussed in Stack Overflow: http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing
|
||||
* -a-singleton-with-javas-enum</p>
|
||||
*
|
||||
@ -56,7 +56,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
* ThreadSafeLazyLoadedIvoryTower} since it doesn't synchronize the whole access method but only the
|
||||
* method internals on specific conditions.</p>
|
||||
*
|
||||
* <p>Yet another way to implement thread safe lazily initialized Singleton can be found in
|
||||
* <p>Yet another way to implement thread-safe lazily initialized Singleton can be found in
|
||||
* {@link InitializingOnDemandHolderIdiom}. However, this implementation requires at least Java 8
|
||||
* API level to work.</p>
|
||||
*/
|
||||
|
@ -20,10 +20,10 @@ change its class.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> When observing a mammoth in its natural habitat it seems to change its behavior based on the
|
||||
> situation. It may first appear calm but over time when it detects a threat it gets angry and
|
||||
> situation. It may first appear calm, but over time when it detects a threat, it gets angry and
|
||||
> dangerous to its surroundings.
|
||||
|
||||
In plain words
|
||||
@ -125,7 +125,7 @@ public class Mammoth {
|
||||
}
|
||||
```
|
||||
|
||||
And here is the full example how the mammoth behaves over time.
|
||||
Here is the full example of how the mammoth behaves over time.
|
||||
|
||||
```java
|
||||
var mammoth = new Mammoth();
|
||||
@ -156,7 +156,7 @@ Use the State pattern in either of the following cases
|
||||
* An object's behavior depends on its state, and it must change its behavior at run-time depending on that state
|
||||
* Operations have large, multipart conditional statements that depend on the object's state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure. The State pattern puts each branch of the conditional in a separate class. This lets you treat the object's state as an object in its own right that can vary independently from other objects.
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [javax.faces.lifecycle.Lifecycle#execute()](http://docs.oracle.com/javaee/7/api/javax/faces/lifecycle/Lifecycle.html#execute-javax.faces.context.FacesContext-) controlled by [FacesServlet](http://docs.oracle.com/javaee/7/api/javax/faces/webapp/FacesServlet.html), the behavior is dependent on current phase of lifecycle.
|
||||
* [JDiameter - Diameter State Machine](https://github.com/npathai/jdiameter/blob/master/core/jdiameter/api/src/main/java/org/jdiameter/api/app/State.java)
|
||||
|
@ -24,7 +24,7 @@
|
||||
package com.iluwatar.state;
|
||||
|
||||
/**
|
||||
* In State pattern the container object has an internal state object that defines the current
|
||||
* In the State pattern, the container object has an internal state object that defines the current
|
||||
* behavior. The state object can be changed to alter the behavior.
|
||||
*
|
||||
* <p>This can be a cleaner way for an object to change its behavior at runtime without resorting
|
||||
|
@ -31,5 +31,4 @@ public interface State {
|
||||
void onEnterState();
|
||||
|
||||
void observe();
|
||||
|
||||
}
|
||||
|
@ -16,18 +16,18 @@ Policy
|
||||
## Intent
|
||||
|
||||
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets
|
||||
the algorithm vary independently from clients that use it.
|
||||
the algorithm vary independently from the clients that use it.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> Slaying dragons is a dangerous job. With experience it becomes easier. Veteran
|
||||
> Slaying dragons is a dangerous job. With experience, it becomes easier. Veteran
|
||||
> dragonslayers have developed different fighting strategies against different types of dragons.
|
||||
|
||||
In plain words
|
||||
|
||||
> Strategy pattern allows choosing the best suited algorithm at runtime.
|
||||
> Strategy pattern allows choosing the best-suited algorithm at runtime.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
@ -36,7 +36,7 @@ Wikipedia says
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
Let's first introduce the dragon slaying strategy interface and its implementations.
|
||||
Let's first introduce the dragon-slaying strategy interface and its implementations.
|
||||
|
||||
```java
|
||||
@FunctionalInterface
|
||||
@ -73,7 +73,7 @@ public class SpellStrategy implements DragonSlayingStrategy {
|
||||
}
|
||||
```
|
||||
|
||||
And here is the mighty dragonslayer, who is able to pick his fighting strategy based on the
|
||||
And here is the mighty dragonslayer, who can pick his fighting strategy based on the
|
||||
opponent.
|
||||
|
||||
```java
|
||||
@ -95,7 +95,7 @@ public class DragonSlayer {
|
||||
}
|
||||
```
|
||||
|
||||
Finally here's the dragonslayer in action.
|
||||
Finally, here's the dragonslayer in action.
|
||||
|
||||
```java
|
||||
LOGGER.info("Green dragon spotted ahead!");
|
||||
@ -120,7 +120,7 @@ Program output:
|
||||
You cast the spell of disintegration and the dragon vaporizes in a pile of dust!
|
||||
```
|
||||
|
||||
What's more, the new feature Lambda Expressions in Java 8 provides another approach for the implementation:
|
||||
What's more, the lambda expressions in Java 8 provides another approach for the implementation:
|
||||
|
||||
```java
|
||||
public class LambdaStrategy {
|
||||
@ -163,7 +163,7 @@ And here's the dragonslayer in action.
|
||||
dragonSlayer.goToBattle();
|
||||
```
|
||||
|
||||
Program output is the same as above one.
|
||||
The program output is the same as the above one.
|
||||
|
||||
## Class diagram
|
||||
|
||||
@ -175,8 +175,8 @@ Use the Strategy pattern when
|
||||
|
||||
* Many related classes differ only in their behavior. Strategies provide a way to configure a class either one of many behaviors
|
||||
* You need different variants of an algorithm. for example, you might define algorithms reflecting different space/time trade-offs. Strategies can be used when these variants are implemented as a class hierarchy of algorithms
|
||||
* An algorithm uses data that clients shouldn't know about. Use the Strategy pattern to avoid exposing complex, algorithm-specific data structures
|
||||
* A class defines many behaviors, and these appear as multiple conditional statements in its operations. Instead of many conditionals, move related conditional branches into their own Strategy class
|
||||
* An algorithm uses data that clients shouldn't know about. Use the Strategy pattern to avoid exposing complex algorithm-specific data structures
|
||||
* A class defines many behaviors, and these appear as multiple conditional statements in its operations. Instead of many conditionals, move the related conditional branches into their own Strategy class
|
||||
|
||||
## Tutorial
|
||||
|
||||
|
@ -31,7 +31,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
* enables an algorithm's behavior to be selected at runtime.</p>
|
||||
*
|
||||
* <p>Before Java 8 the Strategies needed to be separate classes forcing the developer
|
||||
* to write lots of boilerplate code. With modern Java it is easy to pass behavior
|
||||
* to write lots of boilerplate code. With modern Java, it is easy to pass behavior
|
||||
* with method references and lambdas making the code shorter and more readable.</p>
|
||||
*
|
||||
* <p>In this example ({@link DragonSlayingStrategy}) encapsulates an algorithm. The containing
|
||||
|
@ -17,10 +17,11 @@ structure.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> The general steps in stealing an item are the same. First you pick the target, next you confuse
|
||||
> him somehow and finally you steal the item. However there are many ways to implement these steps.
|
||||
> The general steps in stealing an item are the same. First, you pick the target, next you confuse
|
||||
> him somehow and finally, you steal the item. However, there are many ways to implement these
|
||||
> steps.
|
||||
|
||||
In plain words
|
||||
|
||||
@ -117,7 +118,7 @@ public class HalflingThief {
|
||||
}
|
||||
```
|
||||
|
||||
And finally we show how the halfling thief utilizes the different stealing methods.
|
||||
And finally, we show how the halfling thief utilizes the different stealing methods.
|
||||
|
||||
```java
|
||||
var thief = new HalflingThief(new HitAndRunMethod());
|
||||
@ -135,14 +136,14 @@ And finally we show how the halfling thief utilizes the different stealing metho
|
||||
The Template Method pattern should be used
|
||||
|
||||
* To implement the invariant parts of an algorithm once and leave it up to subclasses to implement the behavior that can vary
|
||||
* When common behavior among subclasses should be factored and localized in a common class to avoid code duplication. This is good example of "refactoring to generalize" as described by Opdyke and Johnson. You first identify the differences in the existing code and then separate the differences into new operations. Finally, you replace the differing code with a template method that calls one of these new operations
|
||||
* When common behavior among subclasses should be factored and localized in a common class to avoid code duplication. This is a good example of "refactoring to generalize" as described by Opdyke and Johnson. You first identify the differences in the existing code and then separate the differences into new operations. Finally, you replace the differing code with a template method that calls one of these new operations
|
||||
* To control subclasses extensions. You can define a template method that calls "hook" operations at specific points, thereby permitting extensions only at those points
|
||||
|
||||
## Tutorial
|
||||
## Tutorials
|
||||
|
||||
* [Template-method Pattern Tutorial](https://www.journaldev.com/1763/template-method-design-pattern-in-java)
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [javax.servlet.GenericServlet.init](https://jakarta.ee/specifications/servlet/4.0/apidocs/javax/servlet/GenericServlet.html#init--):
|
||||
Method `GenericServlet.init(ServletConfig config)` calls the parameterless method `GenericServlet.init()` which is intended to be overridden in subclasses.
|
||||
|
@ -16,11 +16,11 @@ define a new operation without changing the classes of the elements on which it
|
||||
|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
Real-world example
|
||||
|
||||
> Consider a tree structure with army units. Commander has two sergeants under it and each sergeant
|
||||
> has three soldiers under them. Given that the hierarchy implements the visitor pattern, we can
|
||||
> easily create new objects that interact with the commander, sergeants, soldiers or all of them.
|
||||
> easily create new objects that interact with the commander, sergeants, soldiers, or all of them.
|
||||
|
||||
In plain words
|
||||
|
||||
@ -214,7 +214,7 @@ Use the Visitor pattern when
|
||||
* Many distinct and unrelated operations need to be performed on objects in an object structure, and you want to avoid "polluting" their classes with these operations. Visitor lets you keep related operations together by defining them in one class. When the object structure is shared by many applications, use Visitor to put operations in just those applications that need them.
|
||||
* The classes defining the object structure rarely change, but you often want to define new operations over the structure. Changing the object structure classes requires redefining the interface to all visitors, which is potentially costly. If the object structure classes change often, then it's probably better to define the operations in those classes.
|
||||
|
||||
## Real world examples
|
||||
## Known uses
|
||||
|
||||
* [Apache Wicket](https://github.com/apache/wicket) component tree, see [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)
|
||||
* [javax.lang.model.element.AnnotationValue](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValue.html) and [AnnotationValueVisitor](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValueVisitor.html)
|
||||
|
@ -24,8 +24,8 @@
|
||||
package com.iluwatar.visitor;
|
||||
|
||||
/**
|
||||
* <p>Visitor pattern defines mechanism to apply operations on nodes in hierarchy. New operations
|
||||
* can be added without altering the node interface.</p>
|
||||
* <p>Visitor pattern defines a mechanism to apply operations on nodes in a hierarchy. New
|
||||
* operations can be added without altering the node interface.</p>
|
||||
*
|
||||
* <p>In this example there is a unit hierarchy beginning from {@link Commander}. This hierarchy is
|
||||
* traversed by visitors. {@link SoldierVisitor} applies its operation on {@link Soldier}s, {@link
|
||||
|
Loading…
x
Reference in New Issue
Block a user