Patrón Observer en Flutter

- Andrés Cruz

Patrón Observer en Flutter

En programación reactiva, hay una entidad que envía eventos y hay otra entidad que suscribe esos eventos, no importa si son 1 o miles, pero estaremos atentos a cambios en esos datos. Y simplemente vamos a reaccionar a esos eventos.

El patrón Observer es un patrón más de los que existen para el diseño de software que define una dependencia uno-a-muchos entre objetos , donde un objeto, llamado el sujeto o el "observado", mantiene una lista de sus dependientes, llamados "observadores", y notifica automáticamente a sus observadores cuando su estado cambia. Los observadores pueden entonces actualizar su estado o realizar otra acción en respuesta al cambio del sujeto es así de simple. en Flutter esto tiene una gran importancia ya que, como estan construido cada uno de los widtets, en forma de arbol, resulta muy dificil comunicar los mismos si no se utilizan esquemas como patrones de diseño o manejadores de estados.

Este patrón permite que objetos relacionados se mantengan en sincronía y reaccionen automáticamente a los cambios en el objeto observado, lo cual es excelente en Flutter gracias a su componente reactivo; con esto se facilita la coordinación y la comunicación entre los componentes de un sistema.

El patrón Observer se utiliza ampliamente en el desarrollo de software y se considera una buena práctica de diseño de software. Es comúnmente utilizado en la implementación de interfaces gráficas de usuario y aplicaciones de tiempo real como chats, notificaciones, transmisiones, entre otros.

El patrón Observer nos ayuda a suscribirnos a algunos eventos de una Clase y recibir notificaciones. Esto quiere decir que hay alguien que emite datos y otro que los va a escuchar. Quien emite los datos simplemente se encarga de enviarlos a quien está suscrito a esos datos y nada más. Las entidades que están escuchando se pueden quitar o poner, y para la otra entidad es totalmente transparente.

Beneficios
Acoplamiento abstracto entre Sujeto y Observador. Todo lo que un sujeto sabe es que tiene una lista de observadores, cada uno de los cuales se ajusta a la interfaz simple de la clase Observer abstracta. El sujeto no conoce la clase concreta de ningún observador. Así, el acoplamiento entre sujetos y observadores es abstracto y mínimo.
Soporte para la comunicación de difusión. A diferencia de una solicitud ordinaria, la notificación que envía un sujeto no necesita especificar su destinatario. La notificación se transmite automáticamente a todos los objetos interesados que se suscribieron a ella. Al sujeto no le importa cuántos objetos interesados existen; su única responsabilidad es notificar a sus observadores. Esto le da la libertad de agregar y eliminar observadores en cualquier momento. Depende del observador manejar o ignorar una notificación.

Inconvenientes

Actualizaciones inesperadas. Debido a que los observadores no tienen conocimiento de la presencia de los demás, pueden estar ciegos al costo final de cambiar de tema. Una operación aparentemente inocua sobre el tema puede provocar una cascada de actualizaciones en los observadores y sus objetos dependientes.

¿Cuándo usarlo el patrón de observer?

  • Cuando varias vistas dependen de un dato, podemos suscribirnos a los eventos de esos datos y, cuando cambia, actualizamos todas las vistas de forma reactiva.
  • Cuando una abstracción tiene dos aspectos, uno dependiente del otro. Encapsular estos aspectos en objetos separados le permite variarlos y reutilizarlos de forma independiente.
  • Cuando un cambio en un objeto requiere cambiar otros y no sabe cuántos objetos necesita cambiar.
  • Cuando un objeto debería poder notificar a otros objetos sin hacer suposiciones sobre quiénes son estos objetos. En otras palabras, no desea que estos objetos estén estrechamente acoplados.

Observador en Flutter

Para nuestro ejemplo, vamos a empezar creando dos interfaces o Clases Abstractas en Dart, que nos ayudarán a delegar la comunicación entre Clases. El primero es el Observable y el otro es el Observador.

El Observador será el que notificará todos los eventos del Observable. Aquí vamos a tener ciertas funciones, la principal es agregar un observador. También creamos una función para eliminar el observador. Y por último les vamos a avisar, es decir avisar que ha cambiado un valor, en este caso un doble.

import 'package:design_patterns/design_patterns/observer/observable/observer.dart';

abstract class Observable {
  void addObserver(Observer observer) {}
  void removeObserver(Observer observer) {}
  void notifyObservers(double newValue) {}
}

El Observador es el encargado de notificar el cambio. Con estas dos interfaces ya tenemos que el Observable va a recibir un Observador y lo vamos a suscribir o desuscribir. Cuando el Observable va a notificar un cambio, lo hace a través del método applyObservers y el Observer tendrá una devolución de llamada que notificará el cambio.

abstract class Observer {
  void notifyChange(double newValue) {}
}

Ahora creamos una Clase AvailableBalanceObservable que se encarga de manejar los eventos de saldo disponible. En esta clase implementamos el Observable. Esto nos obliga a implementar los métodos addObserver, removeObserver y notificarObservers.

Para dar de alta a los observadores, debemos guardarlos en memoria, para ello creamos una variable _amountObserverList donde tenemos la lista de nuestros Observadores. Del mismo modo para eliminar un observador.

Cuando vamos a generar un cambio y vamos a avisar a todos, lo que hacemos es que avisamos a cada uno de los Observadores que tenemos.

Ahora creamos la función para cambiar el saldo disponible. Cuando actualizamos la cantidad, también notificamos a los Observadores.

import 'package:design_patterns/design_patterns/observer/observable/observable.dart';
import 'package:design_patterns/design_patterns/observer/observable/observer.dart';

class AvailableBalanceObservable implements Observable {
  final List<Observer> _amountObserverList = [];
  double _amount = 0.0;

  void changeAmount(double newValue) {
    _amount = newValue;
    notifyObservers(_amount);
  }

  @override
  void addObserver(Observer observer) {
    _amountObserverList.add(observer);
  }

  @override
  void removeObserver(Observer observer) {
    _amountObserverList.remove(observer);
  }

  @override
  void notifyObservers(double newValue) {
    for (var observer in _amountObserverList) {
      observer.notifyChange(newValue);
    }
  }
}

Artículo original:

https://medium.com/@alvaro.armijoss/proxy-in-flutter-bbbbea4f29a6

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.