El patrón Factory es uno de los patrones fundamentales a nivel de diseño orientado a objeto. Este patrón pertenece al grupo de patrones creacionales y nos simplifica la construcción de una jerarquía de clases. Sin embargo a veces a la gente le cuesta ver como usar este patrón en su código. Vamos a utilizar un ejemplo sencillo en el que tendremos una jerarquía de clases Factura como se muestra a continuación.
Vamos a ver cada clase en código:
package com.arquitecturajava; public abstract class Factura { private int id; private double importe; public int getId() { return id; } public void setId(int id) { this.id = id; } public double getImporte() { return importe; } public void setImporte(double importe) { this.importe = importe; } public abstract double getImporteIva(); }
package com.arquitecturajava; public class FacturaIvaReducido extends Factura{ @Override public double getImporteIva() { // TODO Auto-generated method stub return getImporte()*1.07; } }
package com.arquitecturajava; public class FacturaIva extends Factura { @Override public double getImporteIva() { // TODO Auto-generated method stub return getImporte() * 1.21; } }
Clases de Factura
Ya disponemos de las tres clases la clase abstracta y sus clases hijas. Como vemos la clase Factura es una clase abstracta de la cual heredan nuestras dos clases concretas que implementan el cálculo del IVA.
Vamos a construir una Factoría para que se encargue de construir ambos objetos de la jerarquía.
package com.arquitecturajava; public class FactoriaFacturas { public static Factura getFactura(String tipo) { if (tipo.equals("iva")) { return new FacturaIva(); } else { return new FacturaIvaReducido(); } } }
Si nos fijamos la clase lo único que hace es instanciar un objeto u otro dependiendo del tipo que le solicitemos.Eso en un principio parece poco práctico. Pero vamos a ver como queda el programa main:
package com.arquitecturajava; public class Principal { public static void main(String[] args) { Factura f = FactoriaFacturas.getFactura("iva"); f.setId(1); f.setImporte(100); System.out.println(f.getImporteIva()); } }
El patrón Factory Encapsulación
Nos podemos dar cuenta que el programador ya solo tiene que tratar con el concepto de Factura para el la clase FacturaIva y FacturaReducido no existen.
Esto permite una simplificación a la hora de trabajar clara. Es cierto que las Factorias se encargan de generar una jerarquía de clases pero su función fundamental es encapsular una jerarquía de objetos y reducir el conjunto de conceptos con los que trabajamos. Un ejemplo por ejemplo muy clásico es Calendar.getInstance que nos devuelve una de las posibles implementaciones del calendario. No tenemos porque conocer que existe Gregorian calendar.
Muy buena explicación. Este Blog me parece un sitio donde dan contenido simple pero de alta calidad. Gracias los contenidos
Saludos
gracias 🙂
Los botones de compartir entorpecen enormemente la lectura del artículo
Anda no me había dado cuenta , que estas desde una tablet o desde un móvil?. Gracias por el aporte
[…] artículos relacionados : Patrón Factory , Patrón […]
[…] artículos relacionados: Patrón Factoría , Patrón […]
Muchas gracias por el aporte, últimamente estoy intentando comprender los patrones y el diseño OO en general. He visto aplicar este patrón de varias maneras diferentes pero esta, ¿no infringe el principio Open-Closed?. Si queremos un IVA diferente, está bien tener que crear una nueva clase para ello, pero también habría que modificar FactoriaFactura. if(tipo.equals(“iva”)) return new FacturaIva(); else if(tipo.equals(“ivaX”)) return new FacturaIvaX(); else return new FacturaIvaReducido(); Corrígeme si me equivoco pero, ¿no sería mejor crear una interface y tener una sola clase Factura con un atributo de ese tipo?, y así crear distintas clases IVA que la implementen como… Read more »
Si quisieras ser estricto podría usar el api de reflection para instanciar los distintos tipos de objetos de la factoria 🙂
Es otra posibilidad (aunque personalmente no me gusta el uso de reflection a no ser que sea estrictamente necesario), es lo bonito de la programación, nadie tiene la respuesta única y definitiva!.
Aunque es cierto que a veces ser estricto de más también trae problemas y puede llevar a construir grandes arquitecturas “por si acaso” que no se van a utilizar jamás jajaj, aún así consideré que era bueno compartir mi punto de vista para los que se pasen por aquí, ahora en lugar de llevarse una solución, se llevan 3 😉
Saludos!
Eso de llevarse 3 soluciones en lugar de 1 es lo mejor.
Estoy con José, Yo creo que si además hay alternativa al reflection mejor que mejor, que se suele ser bastante lento y como te despistes te pueden llegar a hacer ejecutar un código que no te interesa. A mí se me ocurrió lo siguiente, si veis inconvenientes me comentáis. public interface IVA { public Double getIVA(); } ******************************** public abstract class Factura implements IVA{ private Double importe; public enum IVA{ GENERAL(Double.valueOf(21)), REDUCIDO(Double.valueOf(10)), SUPERREDUCIDO(Double.valueOf(4)); private final Double value; IVA(Double value){ this.value = value; } public Double getValue(){ return this.value; } }; public Double getImporte() { return this.importe; } public void setImporte(Double… Read more »
Hola
Hola Cecilio, gracias por la explicación del patrón factory
al parecer te falto que el método “getFactura” de la clase “FactoriaFactura” sea de tipo estático, para que la aplicación funcione
saludos
muchas gracias por la correción ricardo.