Patrón Observador

Este post analiza el patrón observador. En nuestras aplicaciones, es muy común cambiar el estado de nuestras clases. Cuando hablamos de estado, nos referimos a sus atributos internos, como por ejemplo, el correo de una persona, la dirección, etc.

En algunas ocasiones, es necesario notificar estos cambios a otras clases o componentes dentro de nuestro sistema, ya que, tienen una dependencia con los objetos actualizados y necesitan utilizar siempre la información más reciente.

Por ejemplo, podríamos tener una aplicación que se encarga de obtener los resultados de una encuesta en tiempo real y necesitamos actualizar los indicadores de desempeño de manera dinámica. Entonces, cada vez que se completa una encuesta, nuestra aplicación debe reflejar el cambio en los indicadores, esto con el fin de tener un dashboard en tiempo real.

Una opción para el diseño de la aplicación anterior es el uso del Patrón Observador, ya que con él, logramos mantener informados a todos los objetos que dependen de un evento o cambio en algún componente específico.

Para comprender mejor este patrón, podemos utilizar el siguiente caso de la vida real. ¿Alguna vez se han suscrito a un servicio específico? (Espero que uno de esos servicios sea este blog 😉 ) Por ejemplo, cuando están siguiendo a una persona en YouTube y cada vez que se estrena un vídeo les llega una notificación al celular o al correo.

Bueno, ese es un claro ejemplo del patrón. Aquí los observadores seríamos nosotros, que recibimos la notificación. El sujeto sería la persona que publica el vídeo nuevo en su canal. Este ejemplo se muestra en este diagrama.

Diagrama que ilustra la función del patrón observador

Ahora bien, también es necesario brindar la posibilidad de no recibir más notificaciones, es decir, dejamos de seguir a la persona o nos desinscribimos del canal.

El libro Head First Design Patterns nos define este patrón de la siguiente forma.

El Patrón Observador define una dependencia de uno a muchos entre objetos, de manera que, cuando un objeto cambia, todas las dependencias son notificadas de manera automática.

En el diagrama anterior podemos ver como SubjectObject tiene muchas dependencias con los diferentes Observers, es decir, tiene una relación de uno a muchos.

Este sería el diagrama de clases sugerido.

Diagrama de clases del patrón observador

ISubject es una interfaz que contiene los métodos necesarios para registrar, remover y notificar a todos los observadores de tipo IObservable.

IObservable es una interfaz que contiene el método para recibir la actualización por parte de cualquier objeto de tipo ISubject.

ConcreteSubject y ConcreteObserver son las implementaciones de las interfaces anteriores. En donde ConcreteSubject define una lista de observadores a los cuales les va a notificar de cualquier cambio. Además cuenta con métodos que definen el estado actual, es decir, si algo cambió o no, los cuales son útiles para determinar si es necesario notificar a los observadores o no.

Por otra parte, ConcreteObserver va a contar con un atributo de tipo ISubject para poder registrarse y removerse de la lista cuando sea necesario.

Aquí estamos poniendo en práctica varios principios de diseño que vimos en post anteriores:

  • Programe en las interfaces y no en las implementaciones.
  • Identifique lo que cambia y apártelo de lo que no cambia.
  • Favorezca composición sobre herencia.

Además de los principios anteriores, este patrón nos brinda uno adicional: Dentro de lo posible, favorezca a diseños desacoplados entre objetos que interactúan entre sí.

Veamos las ventajas de tener un diseño desacoplado en este patrón.

  • El tema (Subject) sólo conoce que los observadores implementan una interfaz. No conoce el detalle de cada uno.
  • Debido a esto, podemos agregar observadores en cualquier momento, inclusive durante tiempo de ejecución.
  • Si agregamos observadores, no es necesario modificar el tema, ya que el único requisito es que implemente la interfaz de observador.
  • Ambos son reutilizables, ya que no dependen el uno del otro.
  • Cualquier cambio realizado en el tema o en los observadores no afectan su contra parte.

Para el ejemplo de este patrón, utilicé varios dashboards (observadores) que se encargan de mostrar información de una encuesta (tema o subject) con diferentes formatos.

Cada vez que se reciben nuevos datos de la encuesta, esta se encarga de notificarle a los observadores para que actualicen la información de manera automática.

Este sería el diagrama de ejemplo.

Diagrama de clases del ejemplo que utiliza el patrón observador

Al ejecutar el código de este ejemplo el resultado es el siguiente.

Resultado de ejecutar el código del patrón observador

Para demostrar que todos los observadores son actualizados automáticamente, le agregué un sleep de 5 segundos entre cada actualización de los datos de la encuesta.

El código de ejemplo lo pueden descargar aquí.

En el próximo post vamos a analizar el Patrón Observador que ofrece Java por defecto. Este patrón es muy utilizado internamente por varias clases de Java, así que vamos a revisarlo, ya que es una alternativa muy interesante.

Recordá suscribirte aquí para recibir las últimas actualizaciones todas las semanas.

Referencias:
Libro Head First Design Patterns. Versión digital.

Leave a Reply

Your email address will not be published. Required fields are marked *