Patrones de diseño en JavaScript: técnicas avanzadas con ejemplos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Patrones de diseño avanzados en JavaScript: de la teoría a la práctica

\n\n

Los patrones de diseño son soluciones probadas para problemas típicos en el desarrollo de software. Para un desarrollador de JavaScript que trabaja con Node.js, comprender los patrones avanzados abre el camino para crear sistemas escalables, flexibles y fáciles de mantener. En este artículo, analizaremos cuatro patrones clave: Observer, Proxy, Chain of Responsibility y Strategy. Cada uno será ilustrado con un ejemplo práctico en Node.js.

\n\n

1. Patrón Observer (Observador): arquitectura basada en eventos en Node.js

\n\n

Observer es uno de los patrones de comportamiento fundamentales. Define una dependencia de "uno a muchos" entre objetos: cuando un objeto (sujeto) cambia su estado, todos los objetos dependientes (observadores) son notificados y actualizados automáticamente. En Node.js, este patrón es la base del módulo EventEmitter.

\n\n

Ejemplo: sistema de notificaciones para una tienda en línea

\n

Imaginemos que tenemos un servidor que gestiona pedidos. Al cambiar el estado de un pedido, es necesario notificar a varios subsistemas: registro (logging), envío de correo electrónico y actualización de análisis.

\n\n
const EventEmitter = require('events');\n\n// Sujeto (Subject)\nclass OrderManager extends EventEmitter {\n    constructor() {\n        super();\n        this.orders = [];\n    }\n\n    createOrder(orderId, items) {\n        const order = { orderId, items, status: 'created', createdAt: new Date() };\n        this.orders.push(order);\n        this.emit('order:created', order);\n        return order;\n    }\n\n    updateStatus(orderId, newStatus) {\n        const order = this.orders.find(o => o.orderId === orderId);\n        if (order) {\n            order.status = newStatus;\n            this.emit('order:statusChanged', order);\n        }\n    }\n}\n\n// Observadores (Observers)\nfunction logObserver(order) {\n    console.log(`[LOG] Order ${order.orderId}: status changed to ${order.status} at ${new Date().toISOString()}`);\n}\n\nfunction emailObserver(order) {\n    console.log(`[EMAIL] Sending notification for order ${order.orderId} with status ${order.status}`);\n}\n\nfunction analyticsObserver(order) {\n    console.log(`[ANALYTICS] Recording event: order ${order.orderId} -> ${order.status}`);\n}\n\n// Uso\nconst manager = new OrderManager();\nmanager.on('order:created', logObserver);\nmanager.on('order:statusChanged', logObserver);\nmanager.on('order:statusChanged', emailObserver);\nmanager.on('order:statusChanged', analyticsObserver);\n\nmanager.createOrder('ORD-001', ['Book', 'Pen']);\nmanager.updateStatus('ORD-001', 'shipped');\n
\n\n

Este enfoque permite agregar o eliminar observadores sin modificar el código del sujeto, lo que hace que el sistema sea flexible y fácilmente extensible.

\n\n

2. Patrón Proxy (Apoderado): control de acceso y almacenamiento en caché

\n\n

Proxy proporciona un objeto sustituto que gestiona el acceso a otro objeto. En JavaScript, este patrón se implementa mediante el objeto incorporado Proxy, que permite interceptar y redefinir operaciones fundamentales (acceso a propiedades, llamadas a funciones, etc.).

\n\n

Ejemplo: proxy de almacenamiento en caché para solicitudes API

\n

Supongamos que tenemos un servicio que realiza costosas solicitudes a una API externa. Queremos almacenar en caché los resultados para evitar llamadas repetidas.

\n\n
// Servicio real (Real Subject)\nclass ExternalApiService {\n    async fetchUser(id) {\n        console.log(`Fetching user ${id} from external API...`);\n        // Simulación de retardo de red\n        await new Promise(resolve => setTimeout(resolve, 1000));\n        return { id, name: `User ${id}`, email: `user${id}@example.com` };\n    }\n}\n\n// Proxy (Proxy)\nclass CachingProxy {\n    constructor(realService) {\n        this.realService = realService;\n        this.cache = new M                

Blogs

Book Recommendations