Problema

Notificar automáticamente a múltiples objetos cuando algo cambia, sin que se conozcan entre sí.

Propósito

Cuando un objeto cambia, notifica automáticamente a todos los interesados. Los observadores se suscriben/desuscriben dinámicamente.

Concepto clave

Suscripción a cambios: Como suscribirse a un canal de YouTube - cuando suben video nuevo, todos los suscriptores reciben notificación automáticamente.

Casos de uso comunes

  • Eventos de dominio en sistemas
  • Notificaciones de cambios de estado
  • Interfaces gráficas reactivas (MVC)
  • Sistemas de logging y auditoría
  • Actualizaciones en tiempo real
  • Sistemas de suscripción/publicación

¿Quién es quién en Observer?

Actor Lo que realmente es Ejemplo Analogía
Subject El observado, mantiene lista de observers OrderSubject - notifica cuando cambia estado Canal de YouTube (publica contenido)
Observer Interfaz que define cómo recibir notificaciones OrderObserver - define onOrderStatusChanged() “Suscriptor” (interfaz para notificaciones)
ConcreteObserver Suscriptores que reaccionan diferente EmailObserver, InventoryObserver Tú, tu amigo (cada uno reacciona diferente)

Diagrama

classDiagram
    namespace ObserverPattern {
        class Subject {
            <<interface>>
            +addObserver(observer)
            +removeObserver(observer)
            +notifyObservers()
        }
        
        class ConcreteSubject {
            -observers: List~Observer~
            -state: State
            +addObserver(observer)
            +removeObserver(observer)
            +notifyObservers()
            +setState(state)
            +getState() State
        }
        
        class Observer {
            <<interface>>
            +update(subject)
        }
        
        class ConcreteObserverA {
            +update(subject)
        }
        
        class ConcreteObserverB {
            +update(subject)
        }
    }
    
    Subject <|.. ConcreteSubject
    Observer <|.. ConcreteObserverA
    Observer <|.. ConcreteObserverB
    ConcreteSubject --> Observer : notifies

Ejemplo práctico

classDiagram
    namespace OrderExample {
        class OrderSubject {
            -observers: List~OrderObserver~
            -order: Order
            +addObserver(observer)
            +removeObserver(observer)
            +notifyObservers()
            +updateOrderStatus(status)
        }
        
        class OrderObserver {
            <<interface>>
            +onOrderStatusChanged(order)
        }
        
        class EmailNotificationObserver {
            -emailService: EmailService
            +onOrderStatusChanged(order)
        }
        
        class InventoryObserver {
            -inventoryService: InventoryService
            +onOrderStatusChanged(order)
        }
        
        class AnalyticsObserver {
            -analyticsService: AnalyticsService
            +onOrderStatusChanged(order)
        }
        
        class AuditObserver {
            -auditService: AuditService
            +onOrderStatusChanged(order)
        }
    }
    
    OrderObserver <|.. EmailNotificationObserver
    OrderObserver <|.. InventoryObserver
    OrderObserver <|.. AnalyticsObserver
    OrderObserver <|.. AuditObserver
    OrderSubject --> OrderObserver

Flujo de notificación

sequenceDiagram
    participant Client
    participant Subject
    participant ObserverA
    participant ObserverB
    participant ObserverC
    
    Client->>Subject: setState(newState)
    Subject->>Subject: state = newState
    Subject->>Subject: notifyObservers()
    
    par Notify all observers
        Subject->>ObserverA: update(this)
        ObserverA->>Subject: getState()
        Subject-->>ObserverA: newState
        ObserverA->>ObserverA: react to change
    and
        Subject->>ObserverB: update(this)
        ObserverB->>Subject: getState()
        Subject-->>ObserverB: newState
        ObserverB->>ObserverB: react to change
    and
        Subject->>ObserverC: update(this)
        ObserverC->>Subject: getState()
        Subject-->>ObserverC: newState
        ObserverC->>ObserverC: react to change
    end

Ventajas

  • Bajo acoplamiento: Subject y observers no se conocen directamente
  • Comunicación dinámica: Observers pueden agregarse/quitarse en runtime
  • Principio abierto/cerrado: Fácil agregar nuevos observers sin modificar subject
  • Broadcast: Un cambio notifica a múltiples objetos automáticamente

Desventajas

  • Complejidad: Puede ser difícil rastrear el flujo de notificaciones
  • Performance: Muchos observers pueden impactar el rendimiento
  • Memory leaks: Observers no removidos pueden causar memory leaks
  • Orden: No garantiza orden específico de notificaciones

Cuándo usar

  • Necesitas notificar múltiples objetos sobre cambios de estado
  • Quieres bajo acoplamiento entre objetos dependientes
  • El número de observers puede variar dinámicamente
  • Implementas patrones como MVC o MVP

Cuándo NO usar

  • Solo tienes un observer (usa referencia directa)
  • Las notificaciones son muy frecuentes y afectan performance
  • La relación entre objects es simple y estática
  • Prefieres comunicación síncrona y directa

Diferencias con otros patrones

  • vs Mediator: Observer es 1-a-muchos (notificaciones), Mediator es muchos-a-muchos (coordinación)
  • vs Publish-Subscribe: Observer conoce al subject, Pub-Sub es completamente desacoplado