Patrón Observer

Problema que resuelve este patrón:
¿Cómo tener una visión actualizada de los datos desde diferentes instancias o módulos de una misma aplicación donde los datos pueden ser modificados?

Para tener una visión actualizada de los datos, las aplicaciones de gestión, la gran mayoría de las veces, implementan esperas activas, lo cual puede bajar el rendimiento del sistema.

El esquema tradicional de solución a este problema es hacer que la aplicación periódicamente se actualice realizando pedidos a la fuente de datos, que puede ser una colección en memoria RAM o en disco duro.

Intención:
  • Mantener distintos objetos relacionados,  relaciones uno-a-muchos (1 : N).
  • Mantener las dependencias entre objetos, sin necesidad de conocer al otro objeto.
Definición – Solución:
  • Patrón de Comportamiento para objetos.

  • El patrón Observador define una dependencia del tipo uno-a-muchos (1: n) entre objetos, de manera que cuando el objeto 1 cambia su estado, el observador se encarga de notificar este cambio a todos los n objetos dependientes para que se actualicen automáticamente.

  • El observador no es un mediador entre los sujetos (objetos que cambian de estado) y los objetos dependientes, ya que el mismo es un objeto dependiente. El observador recibe la orden de actualizar por parte del sujeto "dominante".

  • Distinguimos entonces el objeto observado y los objetos observadores. El objeto observado  debe mantener una relación de los objetos que le observan y una forma de notificarles. Por su parte, los objetos observadores, sean del tipo que sean, deben implementar alguna funcionalidad para actualizarse en función del nuevo estado del objeto observado.

    • Proporciona mecanismos para “registrar” objetos observadores en el objeto observable y notificar a aquellos cuando este sufre una notificación.
    Estructura:


    Este patrón también se conoce como el patrón de publicación-suscripción o modelo-vista. Estos nombres sugieren las ideas básicas del patrón, que son bien sencillas: el objeto de datos, llamémoslo "Sujeto" a partir de ahora, contiene métodos mediante los cuales cualquier objeto observador o vista se puede suscribir a él pasándole una referencia a sí mismo. El Sujeto mantiene así una lista de las referencias a sus observadores.


    Los observadores a su vez están obligados a implementar unos métodos determinados mediante los cuales el Sujeto es capaz de notificar a sus observadores "suscritos" los cambios que sufre para que todos ellos tengan la oportunidad de refrescar el contenido representado. De manera que cuando se produce un cambio en el Sujeto, ejecutado, por ejemplo, por alguno de los observadores, el objeto de datos puede recorrer la lista de observadores avisando a cada uno.

    Ejemplo

    Problema: Consideremos una interfaz de usuario en la que se poseen diferentes representaciones de determinados datos de una aplicación. Las clases que representan los datos (el modelo) y las representaciones gráficas (las vistas) pueden ser reutilizadas independientemente.

    • Una hoja de cálculo, un diagrama de barras y un diagrama de sectores pueden mostrar diferentes presentaciones de los datos de una aplicación, pero cada uno de esos tres objetos pueden ser utilizadas independientemente en otras aplicaciones.
    • Las modificaciones sobre los datos deben repercutir en las tres presentaciones, e incluso podría ocurrir que alguno de los diagramas fuese editable, y modificaciones en él también repercutirían en el resto de diagramas y en los propios datos.



    Solución
     


    Uso:

    -Se utiliza cuando se divide un sistema en clases que cooperan y se desea mantener la consistencia entre objetos relacionados, pero sin que estén altamente acoplados, pues ello comprometería su reutilización.
    – Una abstracción tiene más de un aspecto, unos dependientes de otros,
    – Se desea reutilizar cada uno de ellos independientemente de los otros.
    – El cambio de un objeto requiere cambiar los otros, y no se sabe cuántos objetos deben actualizarse.
    – Un objeto debe notificar ciertos cambios a otros, pero sin saber quiénes son dichos objetos.

    Observaciones:
    •El acoplamiento entre observables y observadores es abstracto y mínimo.
    • La notificación se realiza mediante una difusión en la que el objeto observado no tiene que conocer la identidad de los observadores.
    • A veces se puede producir un problema de actualizaciones“inesperadas” en cascada.
    • Registro de observadores en los observables a través de estructuras asociativas (p.e. tablas hash) cuando hay muchos observables y pocos observadores.
    • A veces puede interesar asociar a un mismo observador varios observables: en estos casos puede ser necesario pasar el objeto observado cuando éste notifica un cambio a los observadores.


    Algunas ventajas y desventajas del patrón Observer son:
    1. Acoplamiento abstracto entre Subject y Observer. Todo lo que un objeto sabe de sus observadores es que tiene una lista de objetos que satisfacen la interfaz Observer. Con lo que podrían incluso pertenecer a dos capas distintas de la arquitectura de la aplicación.
    2. No se especifica el receptor de una actualización. Se envía a todos los objetos interesados
    3. Actualizaciones inesperadas. Se podrían producir actualizaciones en cascada muy ineficientes.