Patrón Abstract Factory

19/Mar/2013 Patrones de Diseño , 13 Comentarios

Hoy les voy a presentar el Patrón Abstract Factory junto con un ejemplo simple hecho en Java. Esto se enmarca dentro de la serie de Patrones de Diseño sobre la que vamos air hablando.

Abstract Factory

El patrón Abstract Factory nos permite crear, mediante una interfaz, conjuntos o familias de objetos (denominados productos) que dependen mutuamuente y todo esto sin especificar cual es el objeto concreto.

¿Que usos tiene el patrón Abstract Factory?

Este patrón se puede aplicar cuando:

  • Un sistema debe ser independiente de como sus objetos son creados.
  • Un sistema debe ser 'configurado' con una cierta familia de productos.
  • Se necesita reforzar la noción de dependencia mutua entre ciertos objetos.

Estructura del Patrón Abstract Factory

Patrón Abstract Factory

El asterisco (*) representa que la clase/operación es abstracta.

Elementos del Patrón Abstract Factory

    FabricaAbstracta*: Define un conjunto de métodos (interfaz) para la creación de productos abstractos.
  • FabricaConcreta1/2: Implementa la interfaz de la FabricaAbstracta para la creación de los distintos productos concretos.
  • ProductoAbstractoA*/B*: Define la interfaz de los objetos de tipo ProductoA/B.
  • ProductoConcretoA1/A2/B1/B2: Implementan su respectiva interfaz representando un producto concreto.

Pros/Contras del Patrón Abstract Factory

  • + Brinda flexibilidad al aislar a las clases concretas.
  • + Facilita cambiar las familias de productos.
  • - Para agregar nuevos productos se deben modificar tanto las fabricas abstractas como las concretas.

Ejemplo del Patrón Abstract Factory

Teniendo en cuenta la siguiente jerarquía de clases, la cual trata de representar muy por arriba dos familias de productos (DVD y BluRay) cada uno con un par de variantes (simple y doble capa) para que permiten mostrar diferentes aspectos a tener en cuenta a la hora de usar este patrón.

Ejemplo del Patrón Abstract Factory

Vemos como sería el producto abstracto:

  1. public abstract class Disco implements Prototipo {
  2. @Override
  3. public abstract Prototipo clone();
  4.  
  5. public abstract String getCapacidad();
  6.  
  7. public abstract String getNombre();
  8.  
  9. public abstract String getPrecio();
  10.  
  11. @Override
  12. public String toString() {
  13. return getNombre() + " (" + getCapacidad() + ")";
  14. }
  15. }

El producto DVD extendemos del Disco

  1. public abstract class DVD extends Disco {
  2. ...
  3. }

Y el producto concreto del DVD extenderá de la anterior clase:

  1. public class DVD_CapaSimple extends DVD {
  2.  
  3. @Override
  4. public Prototipo clone() {
  5. return new DVD_CapaSimple();
  6. }
  7.  
  8. @Override
  9. public String getCapacidad() {
  10. return "4.7GB";
  11. }
  12.  
  13. @Override
  14. public String getNombre() {
  15. return "DVD Capa Simple";
  16. }
  17.  
  18. @Override
  19. public String getPrecio() {
  20. return "5.00$";
  21. }
  22.  
  23. }

Vamos a construir un AbstractFactory que nos permita crear discos de DVD o BluRay de simple y doble capa usando el siguiente diseño:

Ejemplo de Patrón Abstract Factory

La factoría abstracta la definiríamos mediante un interface:

  1. public interface FabricaDiscos {
  2.  
  3. public BluRay crearBluRay();
  4. public DVD crearDVD();
  5. }

Y sobre ese interface implementamos una de las fábricas concretas, en este caso la de FabricaDiscos_CapaSimple:

  1. public class FabricaDiscos_CapaSimple implements FabricaDiscos {
  2.  
  3. @Override
  4. public BluRay crearBluRay() {
  5. return new BluRay_CapaSimple();
  6. }
  7.  
  8. @Override
  9. public DVD crearDVD() {
  10. return new DVD_CapaSimple();
  11. }
  12.  
  13. }

Veamos como quedaría el código fuente en Java para utilizar el patrón Abstract Factory:

  1. FabricaDiscos fabrica;
  2. DVD dvd;
  3. BluRay bluray;
  4.  
  5. fabrica = new FabricaDiscos_CapaSimple();
  6. dvd = fabrica.crearDVD();
  7. bluray = fabrica.crearBluRay();
  8.  
  9. System.out.println(dvd);
  10. System.out.println(bluray);
  11.  
  12. fabrica = new FabricaDiscos_CapaDoble();
  13. dvd = fabrica.crearDVD();
  14. bluray = fabrica.crearBluRay();
  15.  
  16. System.out.println(dvd);
  17. System.out.println(bluray);

En el código vemos que sobre la fábrica podemos crear objetos de diferentes tipos y que podríamos ir creciendo en productos atendiendo a nuestras necesidades.

  1. fabrica = new FabricaDiscos_CapaSimple();
  2. dvd = fabrica.crearDVD();
  3. bluray = fabrica.crearBluRay();

Espero que hayáis podido apreciar la flexibilidad que nos brinda el patrón Abstract Factory.

13 comentarios en “Patrón Abstract Factory”

Feffo

Medgasan

Creo que hay un error de concepto del ejemplo de como usar este patrón. Creo que sería más correcto para que se cumpla el desacoplamiento que el código sea este:

FabricaDiscos fabrica;
Disco dvd; // —–> el disco dvd se referenciará por su objeto padre evitando el acople a la clase concreta del producto.
Disco bluray; // —–> el disco blueray se referenciará por su objeto padre evitando el acople a la clase concreta del producto.

fabrica = new FabricaDiscos_CapaSimple();
dvd = fabrica.crearDVD();
bluray = fabrica.crearBluRay();

System.out.println(dvd);
System.out.println(bluray);

fabrica = new FabricaDiscos_CapaDoble();
dvd = fabrica.crearDVD();
bluray = fabrica.crearBluRay();

System.out.println(dvd);
System.out.println(bluray);

Tal vez este cambio haga que se entienda mejor el objetivo del patrón.

Feffo

Víctor HHH

Soy estudiante de Ingeniería de Software en la Universidad Veracruzana, me causa mucha duda saber que métodos contiene la interfaz de Prototipo ya que no ese muestra en ningún marco de código, creo que solo contiene public abstract Prototipo clone(); pero seria en todo caso incorrecto ya que Prototipo no es ninguna clase y no puede devolver un objeto tipo prototipo, sin mas me gustaría comentar que su post me esta ayudando mucho y me agrada que añadan información que no contiene ninguna otra pagina. Muchas gracias.

Feffo

JOSE CARLOS ARIAS ESPINOSA

Muchas Gracias por tu aportacion, me sirvio de mucho, ya pude entender este Design Pattern 😀

Feffo

Cristian

aun no lo entiendo 🙁 la verdad no veo porque crear tantas clases e ir pasandose los parametro cuando todo s epuede hacer con un interface y su implementacion.

Feffo

martin

es de mala practica poner “public” en una interfaces, ya que si o si todos los metodos deben ser publicos. Lo demás todo bien! me sirvió

Feffo

Juande

Entiendo, parece especialmente útil cuando la factoría es capaz de crear un gran número de elementos, creas la factoría del tipo que necesitas y trabajas con sus productos con los métodos de la interfaz, sin volver a preocuparte por el tipo de producto, no se si es exactamente eso.

Está imagen ilustra a lo que me refiero: http://goo.gl/QGtLlX
Además de Window, existirán MessageBox, ContextMenu, Dialog, etc… y una vez que se crea la factoría del sistema operativo que corresponde la creación y el manejo de los widgets que se creen con la factoría es independiente del sistema. Espero ir encaminado.

Muchas gracias por responder al comentario anterior Daniel.
Un saludo a todos 🙂

Feffo

Daniel

Juande, el patrón Abstract Factory se basa en la creación de objetos mediante el patrón factory con un plus de escalabilidad. Su utilidad aparece en muchas ocaciones, como por ejemplo: Implementamos un carrito de la compra que acepta el € como moneda de pago. Si instanciamos el objeto directamente nos enfrentaremos a varios problemas: Que pasa si añadimos el Dolar? Y si añadimos un sistema de puntos como método de pago? Se trata de entidades muy distintas y con métodos que actuan de manera muy diferente. En este sentido, las factorías ayudan a la encapsulación de sus componentes y la abstracción de cara a otros dominios de la aplicación.

Feffo

Juande

Yo lo que no termino de ver muy claro es la utilidad exacta.

Es decir, no se que ventajas supone crear una factoría de discos de una capa pudiendo llamar en cualquier momento a Disoc d = new DVD_CapaSimple().

Un saludo.

Feffo

martin

que vas a tener menos acoplamiento, ya que donde pongas la linea “Disoc d = new DVD_CapaSimple();” esa clase va a tener que conocer el objeto “DVD_CapaSimple”. Esto puede parecer estupido pero no lo es, mientras menos acoplamiento mejor, si es un proyecto grande y tenes que agregar o modificar algo usando Abstract Factory es mas fácil, por algo es un Patrón de software establecido

Feffo

Cristian

Puedes dar un ejemplo sobre el ACOPLAMIENTO que mencionas? ya que la verdad aun no me queda claro su utlidad en 100% ya que no bastaria con crear una INTERFACE y luego su implementacion y en los CONTROLADORES trabajar con las INTERFACE (services)??

Saludos,

Feffo

Javi

No lo entiendo 🙁

Feffo

Vicente

Pues está muy claro…

Feffo

Vicente

Yo creo que todo esto es un contubernio judeo-masónico-prosoviético-bolchevique de carácter marxista-leninista con proyección internacional. Si me equivoco, por favor, que alguien me rectifique.

System.exit(0);

¿Algo que nos quieras comentar?

Déjanos tu comentario, no te preocupes que tu email no será publicado

*

*