mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-14 12:58:37 +00:00
This commit is contained in:
committed by
GitHub
parent
cd4699df88
commit
d43b21472d
@@ -21,7 +21,7 @@ Ejemplo del mundo real
|
||||
|
||||
> Toma como ejemplo un coche que está formado por muchas partes. Sin embargo, no sabemos si el coche tiene todas las partes o solo una parte de ellas. Nuestros coches son dinámicos y extremadamente flexibles.
|
||||
|
||||
En resumen
|
||||
Dicho de otra forma
|
||||
|
||||
> El patrón Abstract Document permite añadir propiedades a objetos sin que estos sean conscientes de ello.
|
||||
|
||||
@@ -166,7 +166,7 @@ Y finalmente asi es como construimos y usamos el Coche `Car` en un ejemplo compl
|
||||
|
||||
## Diagrama de clases
|
||||
|
||||

|
||||

|
||||
|
||||
## Aplicación
|
||||
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Abstract Factory
|
||||
folder: abstract-factory
|
||||
permalink: /patterns/abstract-factory/
|
||||
categories: Creational
|
||||
language: es
|
||||
tags:
|
||||
- Gang of Four
|
||||
---
|
||||
|
||||
## También conocido como
|
||||
|
||||
Kit
|
||||
|
||||
## Propósito
|
||||
|
||||
Proveer de una interfaz para crear familias de objetos relacionados dependientes sin especificar su clase concreta.
|
||||
|
||||
## Explicación
|
||||
|
||||
Ejemplo del mundo real
|
||||
|
||||
> Para crear un reino necesitamos objetos con una temática común. El reino élfico necesita un rey elfo, un castillo élfico y un ejército élfico mientras que el reino orco necesita un rey orco, un castillo orco y un ejércico orco. Hay una dependencia entre los objetos del reino.
|
||||
|
||||
Dicho de otra forma
|
||||
|
||||
> Una factoría de factorías; una factoría que agrupa otras factorias individuales pero relacionadas/dependientes sin especificar su clase concreta.
|
||||
|
||||
Según Wikipedia
|
||||
|
||||
> El patrón abstract factory provee una forma de encapsular un grupo de factorías individuales que tienen una temática común sin especificar sus clases concretas.
|
||||
|
||||
**Ejemplo Programático**
|
||||
|
||||
Traduciendo el ejemplo anterior sobre los reinos. Primero tenemos algunas interfaces e implementaciones de los objetos del reino.
|
||||
|
||||
```java
|
||||
public interface Castle {
|
||||
String getDescription();
|
||||
}
|
||||
|
||||
public interface King {
|
||||
String getDescription();
|
||||
}
|
||||
|
||||
public interface Army {
|
||||
String getDescription();
|
||||
}
|
||||
|
||||
// Elven implementations ->
|
||||
public class ElfCastle implements Castle {
|
||||
static final String DESCRIPTION = "This is the elven castle!";
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return DESCRIPTION;
|
||||
}
|
||||
}
|
||||
public class ElfKing implements King {
|
||||
static final String DESCRIPTION = "This is the elven king!";
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return DESCRIPTION;
|
||||
}
|
||||
}
|
||||
public class ElfArmy implements Army {
|
||||
static final String DESCRIPTION = "This is the elven Army!";
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return DESCRIPTION;
|
||||
}
|
||||
}
|
||||
|
||||
// Orcish implementations similarly -> ...
|
||||
|
||||
```
|
||||
|
||||
Luego tenemos la abstracción e implementación de la factoría del reino.
|
||||
|
||||
```java
|
||||
public interface KingdomFactory {
|
||||
Castle createCastle();
|
||||
King createKing();
|
||||
Army createArmy();
|
||||
}
|
||||
|
||||
public class ElfKingdomFactory implements KingdomFactory {
|
||||
|
||||
@Override
|
||||
public Castle createCastle() {
|
||||
return new ElfCastle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public King createKing() {
|
||||
return new ElfKing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Army createArmy() {
|
||||
return new ElfArmy();
|
||||
}
|
||||
}
|
||||
|
||||
public class OrcKingdomFactory implements KingdomFactory {
|
||||
|
||||
@Override
|
||||
public Castle createCastle() {
|
||||
return new OrcCastle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public King createKing() {
|
||||
return new OrcKing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Army createArmy() {
|
||||
return new OrcArmy();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Ahora tenemos la factoría abstracta que nos permite hacer familias de objetos relacionados por ejemplo la factoria del reino élfico crea el castillo, rey y ejercito élficos etc.
|
||||
|
||||
|
||||
```java
|
||||
var factory = new ElfKingdomFactory();
|
||||
var castle = factory.createCastle();
|
||||
var king = factory.createKing();
|
||||
var army = factory.createArmy();
|
||||
|
||||
castle.getDescription();
|
||||
king.getDescription();
|
||||
army.getDescription();
|
||||
```
|
||||
|
||||
Output del programa:
|
||||
|
||||
```java
|
||||
This is the elven castle!
|
||||
This is the elven king!
|
||||
This is the elven Army!
|
||||
```
|
||||
|
||||
Ahora podemos diseñar una factoría para nuestras factorías de reinos. En este ejemplo creamos `FactoryMaker`, responsable de devolver una instancia de `ElfKingdomFactory` o `OrcKingdomFactory`.
|
||||
El cliente puede usar `FactoryMaker` para crear una factoría concreta, que a su vez, producirá diferentes objetos concretos (derivados de `Army`, `King`, `Castle`).
|
||||
En este ejemplo también usamos un enum para parametrizar el tipo de factoría de reinos pedirá el cliente.
|
||||
|
||||
```java
|
||||
public static class FactoryMaker {
|
||||
|
||||
public enum KingdomType {
|
||||
ELF, ORC
|
||||
}
|
||||
|
||||
public static KingdomFactory makeFactory(KingdomType type) {
|
||||
switch (type) {
|
||||
case ELF:
|
||||
return new ElfKingdomFactory();
|
||||
case ORC:
|
||||
return new OrcKingdomFactory();
|
||||
default:
|
||||
throw new IllegalArgumentException("KingdomType not supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
var app = new App();
|
||||
|
||||
LOGGER.info("Elf Kingdom");
|
||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
||||
LOGGER.info(app.getArmy().getDescription());
|
||||
LOGGER.info(app.getCastle().getDescription());
|
||||
LOGGER.info(app.getKing().getDescription());
|
||||
|
||||
LOGGER.info("Orc Kingdom");
|
||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
||||
-- similar use of the orc factory
|
||||
}
|
||||
```
|
||||
|
||||
## Diagrama de clases
|
||||
|
||||

|
||||
|
||||
|
||||
## Aplicación
|
||||
|
||||
Usar el patrón Abstract Factory cuando
|
||||
|
||||
* El sistema debe ser agnóstico a como se crean, componen y representan sus objetos.
|
||||
* El sistema debe ser configurado con una de las múltiples familias de productos.
|
||||
* La familia de objetos relacionados está diseñada para ser usada en conjunto y necesitas forzar esta premisa.
|
||||
* Quieres proveer de una librería de productos y solo quieres revelar sus interfaces, no su implementación.
|
||||
* El tiempo de vida de la dependencia es conceptualmente mas corte que el del cliente.
|
||||
* Necesitas un valor en tiempo de ejecución para construir una dependencia.
|
||||
* Quieres decidir que producto de una familia llamar en tiempo de ejecución.
|
||||
* Necesitas proveer de uno o mas parámetros solo conocidos en tiempo de ejecución antes de poder resolver la dependencia.
|
||||
* Necesitas consistencia entre productos.
|
||||
* No quieres cambiar el código existente al añadir nuevos productos o familias de productos al programa.
|
||||
|
||||
Ejemplos de casos de uso
|
||||
|
||||
* Elegir llamar a la implementación correcta de FileSystemAcmeService o DatabaseAcmeService o NetworkAcmeService en tiempo de ejecución.
|
||||
* Escribir test unitarios se hace mucho mas sencillo.
|
||||
* Herramientas UI (User Interface) para diferentes SO (Sistemas Operativos).
|
||||
|
||||
## Consecuencias
|
||||
|
||||
* La inyección de dependencias en java esconde las dependencias de la clase servicio lo que puede llevar a errores de ejecución que se podrian haber evitado al compilar.
|
||||
* Mientras que el patrón es muy bueno creando objetos predefinidos, añadir nuevos puede ser complicado.
|
||||
* El código es mas complicado de lo que deberia porque se añaden muchas interfaces y clases nuevas junto con el patrón.
|
||||
|
||||
## Tutoriales
|
||||
|
||||
* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java)
|
||||
|
||||
## Usos conocidos
|
||||
|
||||
* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)
|
||||
* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)
|
||||
* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)
|
||||
|
||||
## Patrones relacionados
|
||||
|
||||
* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)
|
||||
* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)
|
||||
|
||||
## 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)
|
||||
Reference in New Issue
Block a user