¿QUÉ ES ABSTRACT FACTORY?
Es un patron para construir familia de objetos relacionados, esto nos permite crear una interfaz completa con todos los componentes que necesitemos. No necesitamos especificar la clase concreta.
Es un factory de factories
Analogía del Restaurant
Factory Method:
Restaurant → Crea solo HAMBURGUESAS
- Hamburguesa clásica
- Hamburguesa vegetariana
- Hamburguesa premium Abstract Factory: Restaurant → Crea COMIDAS COMPLETAS
- Entrada + Plato Principal + Postre (Menú Italiano)
- Entrada + Plato Principal + Postre (Menú Mexicano)
- Entrada + Plato Principal + Postre (Menú Japonés)
FACTORY METHOD (Un producto)
┌─────────────────────┐
│ TransporteFactory │
└─────────────────────┘
│
├─ Camión
├─ Barco
└─ Avión
ABSTRACT FACTORY (Familia de productos)
┌─────────────────────┐
│ UIFactory │
└─────────────────────┘
│
├─ WindowsFactory
│ ├─ Button
│ ├─ Window
│ └─ Checkbox
│
├─ MacFactory
│ ├─ Button
│ ├─ Window
│ └─ Checkbox
│
└─ LinuxFactory
├─ Button
├─ Window
└─ Checkbox
ESTRUCTURA DEL PATRÓN
Componentes:
AbstractFactory - Interfaz para crear familias de productos
ConcreteFactory - Implementación específica (ej: WindowsFactory)
AbstractProduct - Interfaz para un tipo de producto (ej: IButton)
ConcreteProduct - Implementación específica (ej: WindowsButton)
Client - Usa solo abstracciones, no clases concretas
Paso 1: Definir AbstractProducts
csharp// Productos abstractos (interfaces)
public interface IButton
{
void Render();
void Click();
}
public interface IWindow
{
void Open();
void Close();
void Maximize();
}
public interface ICheckbox
{
void Render();
void Check();
void Uncheck();
}
Paso 2: Crear ConcreteProducts para cada familia
csharp// ========== FAMILIA WINDOWS ==========
public class WindowsButton : IButton
{
public void Render()
{
Console.WriteLine(" Renderizando botón estilo Windows");
}
public void Click()
{
Console.WriteLine(" Click en botón Windows");
}
}
public class WindowsWindow : IWindow
{
public void Open()
{
Console.WriteLine("🪟 Abriendo ventana Windows");
}
public void Close()
{
Console.WriteLine(" Cerrando ventana Windows");
}
public void Maximize()
{
Console.WriteLine(" Maximizando ventana Windows");
}
}
public class WindowsCheckbox : ICheckbox
{
public void Render()
{
Console.WriteLine(" Renderizando checkbox Windows");
}
public void Check()
{
Console.WriteLine(" Checkbox marcado");
}
public void Uncheck()
{
Console.WriteLine(" Checkbox desmarcado");
}
}
// ========== FAMILIA MAC ==========
public class MacButton : IButton
{
public void Render()
{
Console.WriteLine(" Renderizando botón estilo Mac");
}
public void Click()
{
Console.WriteLine(" Click en botón Mac");
}
}
public class MacWindow : IWindow
{
public void Open()
{
Console.WriteLine("🪟 Abriendo ventana Mac");
}
public void Close()
{
Console.WriteLine(" Cerrando ventana Mac");
}
public void Maximize()
{
Console.WriteLine(" Maximizando ventana Mac");
}
}
public class MacCheckbox : ICheckbox
{
public void Render()
{
Console.WriteLine(" Renderizando checkbox Mac");
}
public void Check()
{
Console.WriteLine(" Checkbox marcado (estilo Mac)");
}
public void Uncheck()
{
Console.WriteLine(" Checkbox desmarcado (estilo Mac)");
}
}
Paso 3: Definir AbstractFactory
csharp// Factory abstracta
public interface IUIFactory
{
IButton CreateButton();
IWindow CreateWindow();
ICheckbox CreateCheckbox();
}
Paso 4: Crear ConcreteFactories
csharp// Factory concreta para Windows
public class WindowsFactory : IUIFactory
{
public IButton CreateButton()
{
return new WindowsButton();
}
public IWindow CreateWindow()
{
return new WindowsWindow();
}
public ICheckbox CreateCheckbox()
{
return new WindowsCheckbox();
}
}
// Factory concreta para Mac
public class MacFactory : IUIFactory
{
public IButton CreateButton()
{
return new MacButton();
}
public IWindow CreateWindow()
{
return new MacWindow();
}
public ICheckbox CreateCheckbox()
{
return new MacCheckbox();
}
}
// Factory concreta para Linux
public class LinuxFactory : IUIFactory
{
public IButton CreateButton()
{
return new LinuxButton();
}
public IWindow CreateWindow()
{
return new LinuxWindow();
}
public ICheckbox CreateCheckbox()
{
return new LinuxCheckbox();
}
}
Paso 5: Cliente que usa la Factory
csharppublic class Aplicacion
{
private IButton _button;
private IWindow _window;
private ICheckbox _checkbox;
// Cliente recibe factory, no sabe qué plataforma es
public Aplicacion(IUIFactory factory)
{
_button = factory.CreateButton();
_window = factory.CreateWindow();
_checkbox = factory.CreateCheckbox();
}
public void Ejecutar()
{
_window.Open();
_button.Render();
_button.Click();
_checkbox.Render();
_checkbox.Check();
_window.Maximize();
}
}
// Uso
var platform = DetectarPlataforma(); // "Windows", "Mac", "Linux"
IUIFactory factory = platform switch
{
"Windows" => new WindowsFactory(),
"Mac" => new MacFactory(),
"Linux" => new LinuxFactory(),
_ => throw new PlatformNotSupportedException()
};
var app = new Aplicacion(factory);
app.Ejecutar();
PARTE 7: CUÁNDO USAR ABSTRACT FACTORY
Usa Abstract Factory cuando:
Necesitas familias de objetos relacionados
UI: Botón + Ventana + Menú para cada plataforma
Temas: Colores + Fuentes + Iconos para cada tema
Los objetos deben ser compatibles entre sí
No puedes mezclar botón de Windows con ventana de Mac
Todos deben ser de la misma familia
Quieres ocultar las implementaciones concretas
Cliente solo ve interfaces
No conoce las clases concretas
Quieres cambiar toda la familia fácilmente
De tema claro a oscuro
De MySQL a PostgreSQL
Tienes múltiples variantes de múltiples productos
3 plataformas × 5 componentes = 15 clases
Necesitas organización
NO uses Abstract Factory cuando:
Solo tienes un tipo de producto
Usa Factory Method
Las familias no son compatibles entre sí
Los objetos son independientes
No hay variaciones de familias
Solo una plataforma, un tema, etc.
Agregarás nuevos productos frecuentemente
Modificarás la interfaz abstracta constantemente
PARTE 8: VENTAJAS Y DESVENTAJAS
Ventajas:
Garantiza compatibilidad
Todos los productos son de la misma familia
Aislamiento de clases concretas
Cliente usa interfaces
Fácil cambiar familias
Solo cambias el factory
Single Responsibility
Creación centralizada
Open/Closed
Nuevas familias sin modificar cliente
Desventajas:
Complejidad
Muchas interfaces y clases
Difícil agregar nuevos productos
Debes modificar la interfaz AbstractFactory
Todas las factories concretas
Rigidez
La estructura está definida desde el inicio
Overkill para casos simples
Factory Method puede ser suficiente
Top comments (0)