💡 Ver Caso Práctico: Ejemplo Práctico del Patrón Chain of Responsibility
Chain of Responsibility (Cadena de Responsabilidad) es un patrón de diseño comportamental que permite pasar solicitudes a lo largo de una cadena de manejadores. Cada manejador decide si procesa la solicitud o la pasa al siguiente de la cadena.
Propósito y Caso de Uso
Utiliza Chain of Responsibility cuando un mismo request deba pasar por varias validaciones o procesamientos secuenciales e independientes (ej. middlewares HTTP: autenticación → rate-limiting → logging), y quieras poder añadir, quitar o reordenar pasos sin tocar los demás. Cada eslabón desconoce el resto de la cadena, solo conoce al siguiente.
Estructura del Patrón
- Manejador (Interfaz): Declara el método
handle()y una referencia opcional al siguiente manejador. - Manejadores Concretos: Implementan una comprobación específica; si no pueden resolverla, delegan al siguiente.
- Cliente: Construye la cadena y envía la solicitud al primer eslabón.
Flujo de Funcionamiento
- Entrada: El cliente envía la solicitud al primer manejador de la cadena.
- Decisión: Cada manejador evalúa si puede procesarla; si no, la pasa al siguiente.
- Fin de cadena: El proceso termina cuando algún manejador resuelve la solicitud o se llega al final sin resolución.
Ejemplos de Implementación Reales
interface Handler {
setNext(handler: Handler): Handler;
handle(request: Request): string | null;
}
abstract class BaseHandler implements Handler {
private next: Handler | null = null;
setNext(handler: Handler): Handler { this.next = handler; return handler; }
handle(request: Request): string | null {
return this.next ? this.next.handle(request) : null;
}
}
class AuthHandler extends BaseHandler {
handle(request: Request): string | null {
if (!request.headers.get('Authorization')) return 'Error 401: no autenticado';
return super.handle(request);
}
}
class RateLimitHandler extends BaseHandler {
handle(request: Request): string | null {
if (request.headers.get('X-Requests') === 'exceeded') return 'Error 429: rate limit';
return super.handle(request);
}
}
const auth = new AuthHandler();
const rateLimit = new RateLimitHandler();
auth.setNext(rateLimit);
const result = auth.handle(new Request('https://api.example.com', { headers: { Authorization: 'Bearer x' } }));
console.log(result); // null -> pasó toda la cadena sin bloqueosCuándo NO usarlo
Si solo hay uno o dos pasos fijos que siempre se ejecutan juntos, encadenar manejadores añade indirección sin beneficio real (YAGNIGlosarioYAGNI (You Aren't Gonna Need It)Principio de Extreme Programming (XP) que establece que un programador no debe añadir funcionalidad hasta que sea estrictamente necesario. Su objetivo es evitar la sobre-ingeniería (over-engineering), previniendo código para funcionalidades hipotéticas.Ver término completo →).