Facade o fachada es un patrón que simplifica la interacción con un sistema complejo.

Definición formal

Es un patrón de diseño estructural que proporciona una interfaz simplificada y unificada para un conjunto de interfaces de subsistemas complejos. Este patrón define una clase de alto nivel que hace que el subsistema sea más fácil de usar, ocultando su complejidad y ofreciendo una interfaz más conveniente para interactuar con él.

Ejemplo práctico

Piensa en un control remoto para la TV. La televisión tiene muchas funciones y configuraciones complejas dentro de ella, pero el control remoto te permite encenderla, cambiar de canal y ajustar el volumen de una manera muy simple. El control remoto es como la fachada, ya que te proporciona una forma sencilla de usar las funciones de la televisión sin tener que lidiar con su complejidad interna.

Mira esta imagen, se notará aún más el ejemplo, tienes el control remoto de un dispositivo de entretenimiento multimedia como lo es el Xiaomi MiBox

Xiaomi MiBox

Aquí el control remoto (facade) tiene botones que te facilitan la vida, nota el botón "Netflix" que mediante un sólo clic (interfaz simplificada) te permite realizar de forma sencilla una operación compleja que consta de varias operaciones (subsistemas complejos).

Ejemplo del patrón Facade con C#

El escenario es el siguiente: Tienes un sistema complejo que maneja la compra de productos en una tienda en línea, y este sistema tiene múltiples subsistemas como Inventario, Pedido, y Envio.

Subsistemas complejos

// Subsistema 1: Inventario
public class Inventario
{
    public bool VerificarStock(int productId)
    {
        // Verificar stock del producto por su Id
        return true; // Aquí iría tu lógica, yo asumiré que hay stock.
    }
}

// Subsistema 2: Ordenes de venta
public class Pedido
{
    public void RealizarPedido(int productId)
    {
        // Colocar el pedido
        Console.WriteLine($"Pedido realizado para el producto {productId}");
    }
}

// Subsistema 3: Envíos
public class Envio
{
    public void EnviarPedido(int productId)
    {
        // Enviar el pedido
        Console.WriteLine($"Pedido enviado para el producto {productId}");
    }
}

Clase Facade

public class OnlineStoreFacade
{
    private Inventario inventario;
    private Pedido pedido;
    private Envio envio;

    public OnlineStoreFacade()
    {
        this.inventario = new Inventario();
        this.pedido = new Pedido();
        this.envio = new Envio();
    }

    public void ComprarProducto(int productId)
    {
    	//Aquí ocultas toda la complejidad de los subsistemas y expones ComprarProducto solamente
        if (inventario.VerificarStock(productId))
        {
            pedido.RealizarPedido(productId);
            envio.EnviarPedido(productId);
            Console.WriteLine("Compra completada con éxito");
        }
        else        
            Console.WriteLine("El producto no tiene stock");        
    }
}

Aplicación del patrón Facade

class Program
{
    static void Main(string[] args)
    {
        OnlineStoreFacade tienda = new OnlineStoreFacade();
        
        int productId = 1; // ID del producto a comprar
        tienda.ComprarProducto(productId); //Usas la interfaz simplificada

        Console.ReadLine();
    }
}

Explicación del código

Subsistemas: Tienes 3 subsistemas Inventario, Pedido, y Envio, cada uno con su propia lógica.

Clase Facade: La clase OnlineStoreFacade simplifica la interacción con estos subsistemas al proporcionar un único método ComprarProducto que se encarga de todo el proceso de compra.

Aplicación del patrón: En la clase Program, creas una instancia de OnlineStoreFacade y llamas al método ComprarProducto con el Id del producto. La fachada se encarga de verificar el stock, realizar el pedido y enviar el producto.

Este patrón de diseño, como has notado, es útil para ocultar la complejidad de un sistema y proporcionar una interfaz más amigable y fácil de usar.

El mismo ejemplo sin Facade

Los subsistemas complejos quedarían como están.

No existiría la clase OnlineStoreFacade.

Lo que cambiaría sería la clase Program.

class Program
{
    static void Main(string[] args)
    {
        Inventario inventario = new Inventario();
        Pedido pedido = new Pedido();
        Envio envio = new Envio();

        int productId = 2; // Id del producto a comprar

        // La lógica de compra queda expuesta
        if (inventario.VerificarStock(productId))
        {
            pedido.RealizarPedido(productId);
            envio.EnviarPedido(productId);
            Console.WriteLine("Compra completada con éxito");
        }
        else        
            Console.WriteLine("El producto no tiene stock");  

        Console.ReadLine();
    }
}

Espero que este ejemplo te haya ayudado a entender este patrón y recuerda que practicando es como te conviertes en un maestro. Puedes seguirme también en mi blog bravedeveloper.com donde hago ejemplos como éste y más!

Éxitos mis cracks! 🐿️🥳

Créditos de imagen de portada: Foto de Hugo Sousa en Unsplash