mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-16 10:59:03 +00:00
ead6373765
* Typo corrections * bridge pattern translated to spanish * builder pattern translated to spanish * context-object pattern translated to spanish * converter pattern translated to spanish * dependency injection pattern translated to spanish * factory pattern translated to spanish * factory-kit pattern translated to spanish * factory-method pattern translated to spanish * monostate pattern translated to spanish * multiton pattern translated to spanish * object mother pattern translated to spanish * object pool pattern translated to spanish * property pattern translated to spanish * prototype pattern translated to spanish * registry pattern translated to spanish * step builder pattern translated to spanish * value object pattern translated to spanish * typo corrections and resources urls refactor * grammar corrections * Add image to each pattern * translate all structural patterns to Spanish --------- Co-authored-by: luismateoh <luismateohm@gmail.com> Co-authored-by: luis.hincapie <luis.hincapie@blankfactor.com>
209 lines
6.5 KiB
Markdown
209 lines
6.5 KiB
Markdown
---
|
|
title: Flyweight
|
|
category: Structural
|
|
language: es
|
|
tag:
|
|
- Gang of Four
|
|
- Performance
|
|
---
|
|
|
|
## Propósito
|
|
|
|
Utilice la compartición para dar soporte a un gran número de objetos finos de forma eficiente.
|
|
|
|
## Explicación
|
|
|
|
Un ejemplo real
|
|
|
|
> La tienda del alquimista tiene estanterías llenas de pociones mágicas. Muchas de las pociones son las mismas, por lo
|
|
> que no es necesario crear un nuevo objeto para cada una de ellas. En su lugar, una instancia de objeto puede
|
|
> representar
|
|
> múltiples elementos de la estantería para que la huella de memoria siga siendo pequeña.
|
|
|
|
En pocas palabras
|
|
|
|
> Se utiliza para minimizar el uso de memoria o los gastos computacionales compartiendo todo lo posible con objetos
|
|
> similares.
|
|
|
|
Wikipedia dice
|
|
|
|
> En programación informática, flyweight es un patrón de diseño de software. Un flyweight es un objeto que minimiza el
|
|
> uso de memoria compartiendo tantos datos como sea posible con otros objetos similares; es una forma de utilizar
|
|
> objetos
|
|
> en grandes cantidades cuando una simple representación repetida utilizaría una cantidad inaceptable de memoria.
|
|
|
|
**Ejemplo programático**
|
|
|
|
Traduciendo nuestro ejemplo de la tienda de alquimia de arriba. En primer lugar, tenemos diferentes tipos de
|
|
pociones `Potion`: `HealingPotion`, `HolyWaterPotion` e `InvisibilityPotion`:
|
|
|
|
```java
|
|
public interface Potion {
|
|
void drink();
|
|
}
|
|
|
|
@Slf4j
|
|
public class HealingPotion implements Potion {
|
|
@Override
|
|
public void drink() {
|
|
LOGGER.info("You feel healed. (Potion={})", System.identityHashCode(this));
|
|
}
|
|
}
|
|
|
|
@Slf4j
|
|
public class HolyWaterPotion implements Potion {
|
|
@Override
|
|
public void drink() {
|
|
LOGGER.info("You feel blessed. (Potion={})", System.identityHashCode(this));
|
|
}
|
|
}
|
|
|
|
@Slf4j
|
|
public class InvisibilityPotion implements Potion {
|
|
@Override
|
|
public void drink() {
|
|
LOGGER.info("You become invisible. (Potion={})", System.identityHashCode(this));
|
|
}
|
|
}
|
|
```
|
|
|
|
Luego la clase Flyweight `PotionFactory`, que es la fábrica para crear pociones.
|
|
|
|
```java
|
|
public class PotionFactory {
|
|
|
|
private final Map<PotionType, Potion> potions;
|
|
|
|
public PotionFactory() {
|
|
potions = new EnumMap<>(PotionType.class);
|
|
}
|
|
|
|
Potion createPotion(PotionType type) {
|
|
var potion = potions.get(type);
|
|
if (potion == null) {
|
|
switch (type) {
|
|
case HEALING -> {
|
|
potion = new HealingPotion();
|
|
potions.put(type, potion);
|
|
}
|
|
case HOLY_WATER -> {
|
|
potion = new HolyWaterPotion();
|
|
potions.put(type, potion);
|
|
}
|
|
case INVISIBILITY -> {
|
|
potion = new InvisibilityPotion();
|
|
potions.put(type, potion);
|
|
}
|
|
default -> {
|
|
}
|
|
}
|
|
}
|
|
return potion;
|
|
}
|
|
}
|
|
```
|
|
|
|
`AlchemistShop` contiene dos estantes de pociones mágicas. Las pociones se crean utilizando la antes
|
|
mencionada `PotionFactory`.
|
|
|
|
```java
|
|
@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);
|
|
}
|
|
}
|
|
```
|
|
|
|
En nuestro escenario, un valiente visitante entra en la tienda del alquimista y se bebe todas las pociones.
|
|
|
|
```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();
|
|
```
|
|
|
|
Salida del programa:
|
|
|
|
```java
|
|
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)
|
|
```
|
|
|
|
## Diagrama de clases
|
|
|
|

|
|
|
|
## Aplicabilidad
|
|
|
|
La eficacia del patrón Flyweight depende en gran medida de cómo y dónde se utilice. Aplique el patrón
|
|
Flyweight cuando se cumplan todas las condiciones siguientes:
|
|
|
|
* Una aplicación utiliza un gran número de objetos.
|
|
* Los costes de almacenamiento son altos debido a la gran cantidad de objetos.
|
|
* La mayor parte del estado de los objetos puede hacerse extrínseco.
|
|
* Muchos grupos de objetos pueden ser reemplazados por relativamente pocos objetos compartidos una vez que el estado extrínseco
|
|
extrínseco.
|
|
* La aplicación no depende de la identidad de los objetos. Dado que los objetos flyweight pueden ser compartidos, las pruebas de identidad
|
|
devolverán verdadero para objetos conceptualmente distintos.
|
|
|
|
## Usos conocidos
|
|
|
|
* [java.lang.Integer#valueOf(int)](http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#valueOf%28int%29) y
|
|
de forma similar para Byte, Carácter y otros tipos envueltos (Wrappers).
|
|
|
|
## Créditos
|
|
|
|
* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)
|
|
* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)
|