Método del observador: patrones de diseño de Python

El método del observador es un patrón de diseño de comportamiento que le permite definir o crear un mecanismo de suscripción para enviar la notificación a los múltiples objetos sobre cualquier evento nuevo que le suceda al objeto que están observando. El sujeto es básicamente observado por múltiples objetos. El sujeto necesita ser monitoreado y cada vez que hay un cambio en el sujeto, los observadores son notificados sobre el cambio. Este patrón define una a muchas dependencias entre objetos para que un objeto cambie de estado, todos sus dependientes se notifican y actualizan automáticamente.
 

Problema sin usar el método del observador

Imagine que desea crear una aplicación de calculadora que tenga diferentes funciones, como sumas, restas, cambiar la base de los números a hexadecimal, decimal y muchas otras funciones. Pero uno de tus amigos está interesado en cambiar la base de su número favorito a un número base octal y aún estás desarrollando la aplicación. Entonces, ¿cuál podría ser la solución a esto? ¿Debería su amigo revisar la aplicación todos los días solo para conocer el estado? Pero no crea que daría lugar a muchas visitas innecesarias a la aplicación que definitivamente no eran necesarias. O puede pensar en eso cada vez que agrega la nueva función y envía la notificación a cada usuario. ¿Está bien? A veces sí, pero no todas las veces. Es posible que algunos usuarios se sientan ofendidos por muchas notificaciones innecesarias que realmente no quieren.
 

Solución usando el método del observador

Analicemos la solución al problema descrito anteriormente. Aquí entra el objeto Sujeto en el centro de atención. Pero también notifica a los otros objetos, por eso generalmente lo llamamos Publisher . Todos los objetos que quieren realizar un seguimiento de los cambios en el estado del editor se denominan suscriptores.
 

Observer-method-solution-diagram

Observador-método-solución-diagrama

Python3

class Subject:
 
    """Represents what is being observed"""
 
    def __init__(self):
 
        """create an empty observer list"""
 
        self._observers = []
 
    def notify(self, modifier = None):
 
        """Alert the observers"""
 
        for observer in self._observers:
            if modifier != observer:
                observer.update(self)
 
    def attach(self, observer):
 
        """If the observer is not in the list,
        append it into the list"""
 
        if observer not in self._observers:
            self._observers.append(observer)
 
    def detach(self, observer):
 
        """Remove the observer from the observer list"""
 
        try:
            self._observers.remove(observer)
        except ValueError:
            pass
 
 
 
class Data(Subject):
 
    """monitor the object"""
 
    def __init__(self, name =''):
        Subject.__init__(self)
        self.name = name
        self._data = 0
 
    @property
    def data(self):
        return self._data
 
    @data.setter
    def data(self, value):
        self._data = value
        self.notify()
 
 
class HexViewer:
 
    """updates the Hewviewer"""
 
    def update(self, subject):
        print('HexViewer: Subject {} has data 0x{:x}'.format(subject.name, subject.data))
 
class OctalViewer:
 
    """updates the Octal viewer"""
 
    def update(self, subject):
        print('OctalViewer: Subject' + str(subject.name) + 'has data '+str(oct(subject.data)))
 
 
class DecimalViewer:
 
    """updates the Decimal viewer"""
 
    def update(self, subject):
        print('DecimalViewer: Subject % s has data % d' % (subject.name, subject.data))
 
"""main function"""
 
if __name__ == "__main__":
 
    """provide the data"""
 
    obj1 = Data('Data 1')
    obj2 = Data('Data 2')
 
    view1 = DecimalViewer()
    view2 = HexViewer()
    view3 = OctalViewer()
 
    obj1.attach(view1)
    obj1.attach(view2)
    obj1.attach(view3)
 
    obj2.attach(view1)
    obj2.attach(view2)
    obj2.attach(view3)
 
    obj1.data = 10
    obj2.data = 15

Diagrama de clase

El siguiente es el diagrama de clases para el método del observador
 

Class-diagram-Observer-method

Clase-diagrama-observador-método

Producción

DecimalViewer: Subject Data 1 has data 10
HexViewer: Subject Data 1 has data 0xa
OctalViewer: SubjectData 1has data 0o12
DecimalViewer: Subject Data 2 has data 15
HexViewer: Subject Data 2 has data 0xf
OctalViewer: SubjectData 2has data 0o17

Ventajas

  • Principio abierto/cerrado: la introducción de clases de suscriptores es mucho más fácil en el método Observer en comparación con otros sin realizar cambios en el código del cliente.
  • Establece Relaciones: Es muy fácil establecer las relaciones en tiempo de ejecución entre los objetos.
  • Descripción: Describe cuidadosamente sobre el acoplamiento presente entre los objetos y el observador. Por lo tanto, no es necesario modificar el Sujeto para agregar o eliminar observadores.

Desventajas

  • Fuga de memoria: Fugas de memoria causadas por un problema de escucha caducado debido al registro explícito y la cancelación del registro de observadores.
  • Notificaciones aleatorias: todos los suscriptores presentes reciben notificaciones en orden aleatorio.
  • Implementaciones riesgosas: si el patrón no se implementa con cuidado, hay grandes posibilidades de que termine con un código de gran complejidad.

Aplicabilidad

  • Dependencia múltiple: debemos usar este patrón cuando varios objetos dependen del estado de un objeto, ya que proporciona un diseño limpio y bien probado para el mismo.
  • Obtención de notificaciones: se utiliza en las redes sociales, fuentes RSS, suscripción por correo electrónico en las que tiene la opción de seguir o suscribirse y recibe la última notificación.
  • Reflexiones del objeto: cuando no acoplamos los objetos con fuerza, entonces el cambio de estado en un objeto debe reflejarse en otro objeto.

Lectura adicional: método del observador en Java
 

Publicación traducida automáticamente

Artículo escrito por chaudhary_19 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *