terminal

codeando_simple

terminal

menu

terminal

search_module

guest@codeandosimple: ~/system/search $ grep -r "" .

Press [ENTER] to execute search

Status

Engine: Ready

Database: Online

Index: V2.1.0_LATEST

bash — cat abstract-factory.md
guest@codeandosimple: ~/blog/design-patterns $ cat abstract-factory.md

Abstract Factory_

// "Hay una fuerza motriz más poderosa que el vapor, la electricidad y la energía atómica: la voluntad" - Albert Einstein

# Propósito

El Abstract Factory define una interfaz para crear una familia de objetos relacionados o que dependen entre sí, sin especificar sus clases concretas.

# Problema

La necesidad de crear familias de productos que, idealmente, deben ser usados juntos, desacoplando el código de creación del código de los productos.

# Solución

La solución que propone el Abstract Factory es:

  • Definir una interfaz para la creación de cada familia de objetos: Crear una interfaz o método abstracto para la creación de familia de productos.

  • Delegar la creación a las subclases, fábricas concretas de cada familia de productos: Cada familia tendrá su propia implementación de estas interfaces.

# Estructura

abstract factory

# Participantes

  • FabricaAbstracta: Interfaz que declara un conjunto de métodos para crear cada uno de los productos abstractos.

  • FabricaConcreta: Implementa los métodos para crear los productos concretos.

  • ProductoAbstracto: Declara una interfaz para un tipo de objeto producto.

  • ProductoConcreto: Define un objeto producto que va a ser creado por la correspondiente fábrica concreta. Implementa la interfaz ProductoAbstracto.

  • Cliente: Sólo usa interfaces declaradas por las clases FabricaAbstracta y ProductoAbstracto.

# Cuándo Usarlo

Este patrón es recomendable cuando:

  • Un sistema debe ser independiente de cómo se crean, componen y representan los productos.

  • Cuando un sistema debe ser configurado con una de múltiples familias de productos.

# Ventajas

  • verified

    Consistencia de Productos: Asegura que los productos que se crean son compatibles entre sí.

  • verified

    Intercambiabilidad: Facilita el cambio entre diferentes familias de productos.

  • verified

    Aislamiento: Separa los detalles de implementación de los productos del código cliente.

# Desventajas

  • warning

    Complejidad: Puede aumentar la complejidad del código debido a la gran cantidad de clases e interfaces involucradas.

  • warning

    Dificultad para agregar nueva familia: La interfaz fábrica abstracta fija los tipos de productos que se pueden crear, por lo que agregar nuevas familias implica cambiar esta interfaz y todas las subclases.

# Ejemplo: Interfaces Gráficas

Pensemos en un módulo de software de creación de interfaces gráficas. Debe estar preparado para funcionar en múltiples sistemas operativos (Windows, MacOS, Linux).

Cada sistema operativo tiene su propia manera de dibujar elementos, como ventanas, botones, cuadros de texto, menúes.

Problema

Los clientes deben poder crear cada familia de elementos correspondientes en base al sistema operativo que estén usando, desacoplando la creación del uso de los elementos.

Solución planteada

Implementamos un Abstract Factory que permite crear toda la familia de objetos para un determinado sistema operativo.

Por un lado las clases de creación correspondientes al Abstract Factory, los creadores concretos para Windows y para MacOS, y por otro las clases de Productos, correspondientes a botón (Button) y cuadro de texto (TextBox), cada una con sus propias implementaciones para Windows y MacOS.

abstract factory

# Código Java

Codificamos en Java lo que preparamos en el diagrama. Definimos interfaces para los elementos básicos de la interfaz de usuario:

interface Button {
    void paint();
}

interface TextBox {
    void render();
}

Creamos implementaciones específicas para cada sistema operativo:

class WindowsButton implements Button {
    public void paint() { 
        System.out.println("Render a button in a Windows style"); 
    }
}

class MacOSButton implements Button {
    public void paint() { 
        System.out.println("Render a button in a MacOS style"); 
    }
}

class WindowsTextBox implements TextBox {
    public void render() { 
        System.out.println("Render a text box in a Windows style"); 
    }
}

Definimos la interfaz para la fábrica abstracta y sus implementaciones:

interface GUIFactory {
    Button createButton();
    TextBox createTextBox();
}

class WindowsFactory implements GUIFactory {
    public Button createButton() { return new WindowsButton(); }
    public TextBox createTextBox() { return new WindowsTextBox(); }
}

El cliente usa la fábrica abstracta:

class Application {
    private Button button;
    private TextBox textBox;

    public Application(GUIFactory factory) {
        button = factory.createButton();
        textBox = factory.createTextBox();
    }

    public void paint() {
        button.paint();
        textBox.render();
    }
}

# Mapeo Participantes

  • GUIFactory (FabricaAbstracta): Interfaz para crear objetos Button y TextBox.

  • WindowsFactory, MacOSFactory (FabricaConcreta): Implementan la creación de la familia de productos para cada sistema operativo.

  • Button, TextBox (ProductoAbstracto): Interfaz de productos.

  • WindowsButton, MacOSButton, WindowsTextBox, MacOSTextBox (ProductoConcreto): Implementaciones específicas de cada producto para cada sistema operativo.

  • Application (Cliente): Usa la fábrica abstracta para crear y manipular objetos de tipo Button y TextBox.

# Conclusiones

Este ejemplo demuestra el uso del Abstract Factory para crear familias de objetos relacionados (botones y cuadros de texto). De esta manera podemos intercambiar fácilmente entre diferentes implementaciones (Windows y MacOS) sin cambiar el código del cliente.

# Patrones relacionados

Factory Method

Las clases FabricaAbstracta suelen implementarse con Factory Methods.

Prototype

Las fábricas abstractas también pueden implementarse usando prototipos.

Singleton

Las fábricas concretas suelen implementarse como Singletons.