task: Explanations and grammar fixes for all the GoF patterns (#1791)

* Grammatical fixes to command pattern

* Update bridge pattern readme

* Fixes to builder pattern grammar

* Update chain of responsibility

* Improvements to the composite example

* Fixes to headings

* Minor updates to decorator pattern

* Update facade

* Update factory example

* Update factory method

* Update flyweight

* Interpreter explanation

* Update iterator readme

* Add explanation for mediator pattern

* Grammatical fixes to memento

* Grammar fixes for observer

* Update explanation for the prototype pattern

* Proxy pattern grammar fixes

* Update singleton

* Grammar fixes to state pattern

* Grammar fixes for strategy

* Grammar fixes, template method

* Grammar fixes for visitor

* Fix typo
This commit is contained in:
Ilkka Seppälä
2021-06-24 15:57:20 +03:00
committed by GitHub
parent bbdff14a66
commit 04bf566dc1
66 changed files with 872 additions and 357 deletions

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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();
}
}