Saltar al contenido

Abstract Factory

Un patrón creacional para producir familias de objetos que tienen que usarse juntos, sin nombrar las clases concretas de cada familia.

7 min. de lectura

Abstract Factory es un patrón creacional que permite producir familias de objetos relacionados sin especificar sus clases concretas.

El problema

AndesShop expande sus ventas a Chile. Cada país tiene su propio formato de factura, su propio comprobante de envío y sus propias reglas de impuestos — y esos tres documentos tienen que ser consistentes entre sí: una factura con formato argentino nunca puede terminar acompañada de una etiqueta de envío con el formato de otro país, porque son documentos que un mismo pedido genera juntos y que un ente regulador puede pedir en conjunto.

Solo con Factory Method, terminarías con un factory por cada documento (uno para facturas, otro para etiquetas, otro para comprobantes de pago), sin ninguna garantía de que, al procesar un pedido chileno, alguien no mezcle por error el factory de factura de Argentina con el de etiqueta de Chile.

La solución

Abstract Factory agrupa un conjunto de Factory Methods relacionados detrás de una única interfaz, de forma que una fábrica concreta produce siempre una familia completa y compatible de objetos. El código cliente solo interactúa con la fábrica abstracta y con las interfaces de los productos — nunca con una clase concreta de ningún país.

Estructura de Abstract Factory: cada fábrica concreta produce una familia completa y el cliente solo conoce la interfaz.

Ejemplo en Java

// Product interfaces
interface Invoice {
    String render();
}

interface ShippingLabel {
    String render();
}

// Concrete products — Argentina
class ArgentinaInvoice implements Invoice {
    public String render() { return "Factura A - CUIT incluido"; }
}
class ArgentinaShippingLabel implements ShippingLabel {
    public String render() { return "Etiqueta AR - Correo Argentino"; }
}

// Concrete products — Chile
class ChileInvoice implements Invoice {
    public String render() { return "Boleta electrónica - RUT incluido"; }
}
class ChileShippingLabel implements ShippingLabel {
    public String render() { return "Etiqueta CL - Chilexpress"; }
}

// Abstract Factory
interface DocumentFactory {
    Invoice createInvoice();
    ShippingLabel createShippingLabel();
}

// Concrete Factories: cada una garantiza una familia consistente
class ArgentinaDocumentFactory implements DocumentFactory {
    public Invoice createInvoice() { return new ArgentinaInvoice(); }
    public ShippingLabel createShippingLabel() { return new ArgentinaShippingLabel(); }
}

class ChileDocumentFactory implements DocumentFactory {
    public Invoice createInvoice() { return new ChileInvoice(); }
    public ShippingLabel createShippingLabel() { return new ChileShippingLabel(); }
}
// Client code: recibe la fábrica que corresponda y nunca mezcla familias
DocumentFactory factory = order.getCountry() == Country.CHILE
    ? new ChileDocumentFactory()
    : new ArgentinaDocumentFactory();

Invoice invoice = factory.createInvoice();
ShippingLabel label = factory.createShippingLabel();

Cuándo usarlo

  • Cuando tu código tiene que trabajar con familias de productos relacionados, y necesitás garantizar que los productos de una familia siempre se usen juntos.
  • Cuando querés dar la posibilidad de configurar el sistema con una de varias familias de productos (por país, por proveedor, por tema visual) sin tocar el código que las consume.

Cuándo evitarlo

Con un único producto (no una familia), o variantes que no necesitan mantenerse consistentes entre sí, Abstract Factory es más estructura de la que hace falta — ahí alcanza con Factory Method.

Ventajas y desventajas

VentajasDesventajas
Garantiza que los productos de una familia sean compatibles entre síEl código puede volverse más complicado, con muchas interfaces y clases nuevas
Evita el acoplamiento entre el código cliente y las clases concretasAgregar un nuevo tipo de producto a la familia obliga a modificar la interfaz de la fábrica y todas sus implementaciones
Sigue el principio de abierto/cerrado al agregar una familia nueva completa

Relación con otros patrones

  • Suele implementarse con un grupo de Factory Methods, uno por cada producto de la familia.
  • Las fábricas concretas suelen implementarse como Singleton, ya que en general alcanza con una instancia por familia.
  • Builder se enfoca en construir un objeto complejo paso a paso; Abstract Factory se enfoca en producir familias de objetos relacionados. Ambos pueden combinarse.

Te sirvió, compartilo

// ¿te sirvió?
// compartilo