Chain of responsability y Observer pattern en JavaScript
Clase 75 de 99 • 30 días de JavaScript
Contenido del curso
Chain of responsability pattern 🔗
El patrón Chain of Responsibility en JavaScript es un patrón de diseño que permite la distribución de responsabilidades entre múltiples objetos. Este patrón permite que varios objetos puedan manejar una solicitud sin tener que conocer a quién se está enviando la solicitud ni cuál es el objeto que la manejará finalmente.
La aplicación del patrón Chain of Responsibility en JavaScript se logra a través de la creación de una cadena de objetos que se comunican entre sí. Cada objeto de la cadena debe tener una referencia al siguiente objeto en la cadena y debe tener la capacidad de manejar la solicitud si lo desea. Si un objeto no puede manejar la solicitud, la pasa al siguiente objeto en la cadena.
Ejemplo de aplicación del patrón Chain of Responsibility en JavaScript:
// Clase base para las solicitudes class Solicitud { constructor(tipo, cantidad) { this.tipo = tipo; this.cantidad = cantidad; this.siguiente = null; } } // Clase manejadora de solicitudes de descuentos class DescuentoHandler { constructor() { this.siguiente = null; } solicitar(solicitud) { if (solicitud.tipo === "descuento") { console.log(`Se aplicó un descuento del 10% por un total de ${solicitud.cantidad * 0.1}`); } else if (this.siguiente !== null) { this.siguiente.solicitar(solicitud); } } } // Clase manejadora de solicitudes de envío gratis class EnvioGratisHandler { constructor() { this.siguiente = null; } solicitar(solicitud) { if (solicitud.cantidad >= 500) { console.log("Se aplicó envío gratis"); } else if (this.siguiente !== null) { this.siguiente.solicitar(solicitud); } } } // Uso const descuentoHandler = new DescuentoHandler(); const envioGratisHandler = new EnvioGratisHandler(); descuentoHandler.siguiente = envioGratisHandler; const solicitud = new Solicitud("descuento", 100); descuentoHandler.solicitar(solicitud); // Se aplicó un descuento del 10% por un total de 10 const solicitud2 = new Solicitud("compra normal", 700); descuentoHandler.solicitar(solicitud2); // Se aplicó envío gratis
Código corregido por @Energy 💚
En este ejemplo, creamos dos clases manejadoras de solicitudes, DescuentoHandler y EnvioGratisHandler, que se encargan de manejar solicitudes específicas. Luego, establecemos una relación de cadena entre ellos, estableciendo que DescuentoHandler es el primer objeto en la cadena y EnvioGratisHandler es el siguiente.
Cuando se hace una solicitud, se inicia en DescuentoHandler, que verifica si puede manejar la solicitud. Si no puede, pasa la solicitud al siguiente objeto en la cadena, EnvioGratisHandler, que verifica si puede manejarla. Si uno de los objetos en la cadena puede manejar la solicitud, se ejecuta su lógica correspondiente y se detiene la cadena. De lo contrario, la solicitud se pierde y no se ejecuta ninguna acción.
Este patrón es útil en situaciones donde una sola clase no debería ser responsable de manejar todas las solicitudes, y en lugar de eso, se deben dividir entre varios objetos. Además, permite que la lógica de manejo de solicitudes sea fácilmente modificable y escalable, ya que se pueden agregar o eliminar objetos de la cadena sin afectar el comportamiento de los objetos existentes.
Observer pattern 👀
El patrón Observer en JavaScript es un patrón de diseño que permite que un objeto mantenga una lista de sus dependientes y notifique a ellos automáticamente cualquier cambio. Este patrón es útil cuando necesitamos que varios objetos reciban notificaciones de cambios en un objeto determinado.
La aplicación del patrón Observer en JavaScript se logra a través de la creación de un objeto que mantiene una lista de sus dependientes y provee una forma de registrarlos y notificarlos de los cambios. Cada objeto dependiente debe tener una función que se ejecute cada vez que se produzca un cambio en el objeto principal.
Ejemplo de aplicación del patrón Observer en JavaScript:
// Clase Observador class Observador { constructor(nombre) { this.nombre = nombre; } notificar(cambio) { console.log(`${this.nombre} ha sido notificado del cambio: ${cambio}`); } } // Clase Observable class Observable { constructor() { this.observadores = []; } registrarObservador(observador) { this.observadores.push(observador); } notificarCambio(cambio) { this.observadores.forEach(observador => { observador.notificar(cambio); }); } } // Uso const observable = new Observable(); const observador1 = new Observador("Observador 1"); const observador2 = new Observador("Observador 2"); observable.registrarObservador(observador1); observable.registrarObservador(observador2); observable.notificarCambio("Cambio en el objeto principal"); // Observador 1 ha sido notificado del cambio: Cambio en el objeto principal // Observador 2 ha sido notificado del cambio: Cambio en el objeto principal
En este ejemplo, creamos una clase Observador y una clase Observable. La clase Observable mantiene una lista de sus dependientes (observadores) y provee una forma de registrarlos y notificarlos de los cambios. Cada vez que se produce un cambio en el objeto principal, se notifica a todos los observadores registrados.
Alejandro Anaya
Brandon James Huamán Mallcco
Nelson Cespedes
Andres Eduardo Maneiro Antunez
Joan Alexander Valerio Rodríguez
Andrés Julian Caro Restrepo
HERNANDO RAMIREZ
Luis Gomero
El ejemplo de la cadena de responsabilidad no está correcto.
Lo he corregido para que funcione como debería de funcionar:
Mis modificaciones: Renombramiento de los métodos de la linea 16 y 31 deberían de ser el mismo, es decir, llamarse por ejemplo 'solicitar()' y en la linea 20 y 35 realizar la llamada así: this.siguiente.solicitar(solicitud)
De esta manera se encadenan con el mismo nombre de método 'solicitar()'
gracias, ya se me hacía raro
Leyenda!!! gracias por ese dato me tenia confundido como se suponía que funcionaria con nombres de funciones diferentes!! excelente observación.
Estuve rato de entender el codigo del Chain of responsability pattern, porque no le veia sentido de porque se llamaban asi mismo si la variable siguiente es null, e incluso lo corri en vscode y generaba error
pero cuando cambie cuando esta el condicional de si la variable siguiente no es null por el metdo de la otra clase en vez de llamarse asi mismo si me funciono, asi que me imagino que es un error en el ejemplo, podrian verificar
en DescuentoHandler
class DescuentoHandler { constructor() { this.siguiente = null; } solicitarDescuento(solicitud) { if (solicitud.tipo === "descuento") { console.log(`Se aplicó un descuento del 10% por un total de ${solicitud.cantidad * 0.1}`); } else if (this.siguiente !== null) { this.siguiente.solicitarDescuento(solicitud); } } }
por
class DescuentoHandler { constructor() { this.siguiente = null; } solicitarDescuento(solicitud) { if (solicitud.tipo === "descuento") { console.log(`Se aplicó un descuento del 10% por un total de ${solicitud.cantidad * 0.1}`); } else if (this.siguiente !== null) { this.siguiente.solicitarEnvioGratis(solicitud); } } }
e hice lo mismo en EnvioGratisHandler
class EnvioGratisHandler { constructor() { this.siguiente = null; } solicitarEnvioGratis(solicitud) { if (solicitud.cantidad >= 500) { console.log("Se aplicó envío gratis"); } else if (this.siguiente !== null) { this.siguiente.solicitarEnvioGratis(solicitud); } } }
por
class EnvioGratisHandler { constructor() { this.siguiente = null; } solicitarEnvioGratis(solicitud) { if (solicitud.cantidad >= 500) { console.log("Se aplicó envío gratis"); } else if (this.siguiente !== null) { this.siguiente.solicitarDescuento(solicitud); } } }
El ejemplo presenta algunos errores... Mi solución:
Podríamos establecer un setter en el que automaticemos la llamada a notificarCambio cada vez que se cambie alguna variable
Creo que la idea es controlar un segundo descuento, pero como principiante no le veo sentido... igual tiene errores el codigo y no se puede validar
OBSERVER ⭐ me recuerda las clases de uso de rxjs en Angular