Observer (Observador o Pub/Sub) es un patrón de diseño comportamental que permite a un objeto (el sujeto o emisor) notificar a otros objetos (los observadores o suscriptores) sobre los cambios en su estado sin acoplar fuertemente las clases.
💡 Ver Caso Práctico: Ejemplo Práctico del Patrón Observer
Propósito y Caso de Uso
Utiliza el patrón Observer cuando un cambio en el estado de un objeto requiera cambiar otros objetos, y no sepa cuántos objetos necesitan cambiar con antelación. Fomenta el cumplimiento del principio de Responsabilidad Única (SOLIDGlosarioSOLIDAcrónimo de cinco principios de diseño orientado a objetos y programación diseñados para hacer que el software sea más comprensible, flexible y mantenible: S - Single Responsibility Principle (Responsabilidad Única) O - Open/Closed Principle (Abierto/Cerrado) L - Liskov Substitution Principle (Sustitución de Liskov) I - Interface Segregation Principle (Segregación de Interfaz) D - Dependency Inversion Principle (Inversión de Dependencias) Ver término completo →) y mantiene el código desacoplado (KISSGlosarioKISS (Keep It Simple, Stupid)Principio de diseño que establece que la mayoría de los sistemas funcionan mejor si se mantienen simples en lugar de hacerlos complejos. Se debe evitar la complejidad innecesaria en la arquitectura y el código.Ver término completo →).
A diferencia de patrones creacionales como el Patrón Singleton o el Patrón Factory Method, Observer gestiona la comunicación dinámica en tiempo de ejecución.
Estructura del Patrón
- Sujeto (Subject / Publisher): Emite eventos de interés y mantiene una lista de suscriptores para notificarles.
- Observador (Observer / Subscriber): Interfaz que declara el método de actualización (
update). - Observadores Concretos: Implementaciones que reaccionan a las notificaciones enviadas por el emisor.
Flujo de Funcionamiento
- Suscripción: Los objetos observadores se registran en el sujeto mediante
.subscribe(observer). - Evento: Ocurre un cambio de estado en el sujeto (ej. nuevo pedido realizado).
- Notificación: El sujeto recorre su lista interna de suscriptores e invoca el método
.update(data)en cada uno de ellos.
Ejemplos de Implementación Reales
interface Observer<T> {
update(data: T): void;
}
class OrderService {
private observers: Observer<{ orderId: string; total: number }>[] = [];
public subscribe(observer: Observer<{ orderId: string; total: number }>): void {
this.observers.push(observer);
}
public unsubscribe(observer: Observer<{ orderId: string; total: number }>): void {
this.observers = this.observers.filter(obs => obs !== observer);
}
public createOrder(orderId: string, total: number): void {
console.log(`Orden ${orderId} creada por $${total}`);
this.notify({ orderId, total });
}
private notify(data: { orderId: string; total: number }): void {
this.observers.forEach(obs => obs.update(data));
}
}
// Observador 1: Correo electrónico
class EmailNotifier implements Observer<{ orderId: string; total: number }> {
update(data: { orderId: string; total: number }): void {
console.log(`[Email] Confirmacion enviada para la orden ${data.orderId}`);
}
}
// Observador 2: Inventario
class InventoryManager implements Observer<{ orderId: string; total: number }> {
update(data: { orderId: string; total: number }): void {
console.log(`[Inventario] Stock actualizado para la orden ${data.orderId}`);
}
}
// Uso:
const orderService = new OrderService();
orderService.subscribe(new EmailNotifier());
orderService.subscribe(new InventoryManager());
orderService.createOrder("ORD-2026-99", 149.99);