Strategy
El patrón que convierte una cadena de if/else en piezas intercambiables — y la forma más directa de cumplir el principio abierto/cerrado.
En esta página
Strategy es un patrón de comportamiento: encapsula una familia de algoritmos intercambiables detrás de una interfaz común, de modo que el código que los usa (el contexto) no sabe — ni le importa — cuál está ejecutando. Es, probablemente, el patrón con mejor relación sencillez/impacto de todo el catálogo.
El problema: el switch que no deja de crecer
function calcularEnvio(pedido: Pedido, metodo: string): number {
if (metodo === 'estandar') {
return pedido.peso * 0.5;
} else if (metodo === 'exprés') {
return pedido.peso * 1.2 + 5;
} else if (metodo === 'recogida') {
return 0;
}
throw new Error(`método desconocido: ${metodo}`);
}
Hoy son tres ramas. Cada transportista nuevo modifica esta función — y de paso toca un fichero que ya funcionaba, con su riesgo de regresión. Si el mismo switch sobre metodo aparece además en la validación y en la UI, tienes el mismo conocimiento repetido en tres sitios: el problema exacto del que habla DRY.
La solución: algoritmos como valores
Cada rama se convierte en una estrategia con la misma firma, y el switch en un mapa:
type EstrategiaEnvio = (pedido: Pedido) => number;
const estrategias: Record<string, EstrategiaEnvio> = {
estandar: (p) => p.peso * 0.5,
expres: (p) => p.peso * 1.2 + 5,
recogida: () => 0,
};
function calcularEnvio(pedido: Pedido, metodo: string): number {
const estrategia = estrategias[metodo];
if (!estrategia) throw new Error(`método desconocido: ${metodo}`);
return estrategia(pedido);
}
El contexto conoce la interfaz, nunca las implementaciones. Añadir una estrategia no toca al contexto: eso es el principio abierto/cerrado en acción.
Añadir un transportista ahora es añadir una entrada al mapa — el contexto queda intacto. El sistema está abierto a extensión, cerrado a modificación: acabas de ver el principio abierto/cerrado de SOLID funcionando, no en un eslogan.
En un lenguaje sin funciones de primera clase, cada estrategia sería una clase con un método (interface EstrategiaEnvio { calcular(p: Pedido): number }). En JavaScript/TypeScript, las funciones ya son objetos: el patrón se disuelve en el lenguaje, pero la idea — y el nombre para comunicarla — sigue siendo la misma.
Ya lo usas todos los días
arr.sort((a, b) => a.precio - b.precio)— el comparador es una estrategia que le inyectas al algoritmo de ordenación.map,filter,reduce— cada callback es la estrategia de qué hacer con cada elemento.- Pasarelas de pago, proveedores de login (Google/GitHub/email), formatos de exportación (CSV/JSON/PDF): un contrato, N implementaciones.
- La compresión de tu servidor HTTP (gzip/brotli según el cliente).