Patrón Chain of Responsibility en C#: Guía Completa

Introducción: Pasar la solicitud

Chain of Responsibility permite enviar una solicitud a través de una cadena de manejadores hasta que uno la procesa. Esto reduce el acoplamiento entre emisor y receptor y facilita introducir nuevos manejadores sin tocar el código cliente.

La cadena puede reordenarse o ampliarse según cambien las reglas del negocio, manteniendo el flujo flexible.

Cadena de eslabones
Prompt: Metal chain close-up, shallow depth of field, industrial aesthetic.

1. Naturaleza: El río y sus filtros

Un río atraviesa capas de roca y arena que filtran impurezas. Cada capa decide qué retener y qué dejar pasar.

Si una capa no puede “resolver” toda la filtración, el flujo continúa a la siguiente, igual que una solicitud que avanza por la cadena.

Río filtrado por capas
Prompt: River cross-section with layered soil filtering water, educational illustration style.

2. Mundo Real: Soporte por niveles

Un ticket pasa por Nivel 1, Nivel 2 y Nivel 3. Cada nivel intenta resolverlo antes de escalar.

Si el problema es simple, se detiene en el primer nivel; si es complejo, avanza sin que el usuario tenga que conocer el proceso interno.

Soporte por niveles
Prompt: Customer support escalation ladder, modern flat infographic style.

3. Implementación en C#: Código Paso a Paso

public abstract class Manejador
{
    protected Manejador _siguiente;
    public void SetSiguiente(Manejador siguiente) => _siguiente = siguiente;
    public abstract void Manejar(int nivel);
}

public class Nivel1 : Manejador
{
    public override void Manejar(int nivel)
    {
        if (nivel <= 1) Console.WriteLine("Nivel 1 resolvió");
        else _siguiente?.Manejar(nivel);
    }
}

public class Nivel2 : Manejador
{
    public override void Manejar(int nivel)
    {
        if (nivel == 2) Console.WriteLine("Nivel 2 resolvió");
        else _siguiente?.Manejar(nivel);
    }
}

public class Nivel3 : Manejador
{
    public override void Manejar(int nivel)
    {
        if (nivel >= 3) Console.WriteLine("Nivel 3 resolvió");
    }
}

// Uso
var n1 = new Nivel1();
var n2 = new Nivel2();
var n3 = new Nivel3();

n1.SetSiguiente(n2);
n2.SetSiguiente(n3);

n1.Manejar(2);

4. Chain vs Pipeline

Chain permite que un manejador detenga la cadena cuando la solicitud ya fue resuelta. Pipeline suele ejecutar todos los pasos, incluso si ya hay un resultado parcial.

Si necesitas rutas alternativas o validaciones opcionales, Chain es más flexible; si quieres un flujo fijo, Pipeline es más directo.

5. Diagrama UML

UML Chain
Prompt: UML diagram of Chain of Responsibility, clean vector layout.
Flujo de la cadena
Prompt: Flow diagram of handlers in sequence, minimal infographic style.

⚠️ Cuándo NO Usar Chain

  • Si siempre sabes quién debe manejar la solicitud.
  • Si el recorrido debe ser fijo y obligatorio.
  • Si necesitas trazabilidad estricta de cada paso y no quieres cortes tempranos.

💪 Ejercicio

Crea una cadena para validar formularios: formato, reglas de negocio, persistencia. Añade un manejador que solo se active si el país es específico.

Conclusión

Chain desacopla el emisor del receptor, haciendo flexible la ruta de procesamiento. Es ideal cuando quieres añadir o reordenar reglas sin tocar el emisor.