Files
2024-10-20 10:22:52 +03:00

134 lines
3.7 KiB
Markdown

---
title: Factory Kit
shortTitle: Factory Kit
category: Creational
language: es
tag:
- Extensibility
---
## También conocido como
Abstract-Factory
## Propósito
Define una fábrica de contenido inmutable con interfaces de constructor y fábrica separadas.
## Explicación
Ejemplo del mundo real
> Imagina una fábrica de armas mágicas que puede crear cualquier tipo de arma que se desee. Cuando la fábrica se
> desempaqueta, el maestro recita los tipos de armas necesarios para prepararla. Después de eso, cualquiera de esos
> tipos
> de armas pueden ser invocados en un instante.
En palabras sencillas
> El kit de fábrica (Kit Factory) es un constructor de objetos configurable, una fábrica para crear fábricas.
**Ejemplo programático**
Definamos primero la interfaz simple arma `Weapon`.
```java
public interface Weapon {
}
public enum WeaponType {
SWORD,
AXE,
BOW,
SPEAR
}
public class Sword implements Weapon {
@Override
public String toString() {
return "Sword";
}
}
// Hacha `Axe`, Arco `Bow` y Lanza `Spear` se definen de forma similar
```
A continuación, definimos una interfaz funcional que permite añadir un constructor con un nombre a la fábrica.
```java
public interface Builder {
void add(WeaponType name, Supplier<Weapon> supplier);
}
```
El núcleo del ejemplo es la interfaz `WeaponFactory` que implementa el patrón de fábrica. El método `#factory` se
utiliza para configurar la fábrica con las clases que necesita para ser capaz de construir. El método `#create` se
utiliza para crear instancias del objeto.
```java
public interface WeaponFactory {
static WeaponFactory factory(Consumer<Builder> consumer) {
var map = new HashMap<WeaponType, Supplier<Weapon>>();
consumer.accept(map::put);
return name -> map.get(name).get();
}
Weapon create(WeaponType name);
}
```
Ahora, podemos mostrar cómo se puede utilizar `WeaponFactory`.
```java
var factory = WeaponFactory.factory(builder -> {
builder.add(WeaponType.SWORD, Sword::new);
builder.add(WeaponType.AXE, Axe::new);
builder.add(WeaponType.SPEAR, Spear::new);
builder.add(WeaponType.BOW, Bow::new);
});
var list = new ArrayList<Weapon>();
list.add(factory.create(WeaponType.AXE));
list.add(factory.create(WeaponType.SPEAR));
list.add(factory.create(WeaponType.SWORD));
list.add(factory.create(WeaponType.BOW));
list.stream().forEach(weapon -> LOGGER.info("{}", weapon.toString()));
```
Esta es la salida de la consola cuando se ejecuta el ejemplo.
```
21:15:49.709 [main] INFO com.iluwatar.factorykit.App - Axe
21:15:49.713 [main] INFO com.iluwatar.factorykit.App - Spear
21:15:49.713 [main] INFO com.iluwatar.factorykit.App - Sword
21:15:49.713 [main] INFO com.iluwatar.factorykit.App - Bow
```
## Diagrama de clases
![alt text](./etc/factory-kit.png "Factory Kit")
## Aplicabilidad
Utilice el patrón Factory Kit cuando
* La clase de fábrica no puede anticipar los tipos de objetos que debe crear.
* Se necesita una nueva instancia de un constructor personalizado en lugar de uno global.
* Los tipos de objetos que la fábrica puede construir necesitan ser definidos fuera de la clase.
* Es necesario separar las interfaces del constructor y del creador.
* Desarrollos de juegos y otras aplicaciones que tienen personalización del usuario
## Patrones relacionados
* [Builder](https://java-design-patterns.com/patterns/builder/)
* [Factory](https://java-design-patterns.com/patterns/factory/)
* [Abstract-Factory](https://java-design-patterns.com/patterns/abstract-factory/)
## Tutoriales
* [Factory kit implementation tutorial](https://diego-pacheco.medium.com/factory-kit-pattern-66d5ccb0c405)
## Créditos
* [Design Pattern Reloaded by Remi Forax](https://www.youtube.com/watch?v=-k2X7guaArU)