Implementación de la suscripción al boletín usando el patrón de diseño Observer en Python

Observer Design Pattern es un patrón de diseño en Python que facilita una relación de uno a muchos. Digamos, por ejemplo, que usted y varios otros lectores se suscribieron a un boletín informativo. Cuando haya un nuevo boletín disponible, lo recibirá junto con otros suscriptores. Supongamos que, si no desea recibir el boletín, puede cancelar su suscripción y no recibirá las nuevas ediciones.

Un patrón de diseño de observador no se limita a la suscripción al boletín. Puede ser cualquier información, como una señal de hilo concurrente, una señal de un sistema operativo, etc. Un patrón de diseño de observador es una forma de patrón de publicación-suscriptor. Facilita la gestión de suscripciones y la difusión de información a los suscriptores.

Beneficios del patrón de diseño del observador

Observer Design Pattern tiene un objeto estático llamado Subject y un objeto variable llamado Observers. Puede haber cero o N número de observadores, que pueden cambiar según la suscripción. Aquí, el Sujeto mantiene a los Observadores, y si alguno de los estados del objeto cambia, el Sujeto notifica a otros Observadores. Por ejemplo, considere el caso de una publicación de LinkedIn. Cuando publica una nueva publicación de LinkedIn (cambio de estado), la línea de tiempo de sus seguidores se actualiza con su nueva publicación.

 Veamos sus beneficios.

  • Facilita un acoplamiento flexible entre Sujeto y Observadores.
  • Los observadores se pueden actualizar en tiempo de ejecución
  • Un sujeto puede mantener cero o N número de observadores
  • La aptitud de transmitir mensajes entre Sujeto y Observadores.

Implementación de suscripción al boletín

Diseñemos un modelo de suscripción de boletín simple para comprender el patrón de diseño del observador. Como comentamos, un patrón de diseño de observador tiene dos objetos principales: Sujeto y Observador. El sujeto puede agregar, eliminar y notificar a los observadores a través de register_observer, unregister_observer y notificar_observer. Mientras que el observador es una interfaz que tiene un método abstracto: notificar.    

Patrón de diseño del observador

Aquí, dos observadores concretos, CompanyNewsletterObserver y ConsumerNewsletterObserver, se derivan de la interfaz Observer. Estos métodos concretos implementan el método abstracto de notificación, y el Sujeto llamará al método de notificación en su método de notificación_observador. Entonces, para enviar información a los suscriptores, simplemente necesitamos llamar al método notificar_observador en el Asunto. Veamos la implementación.

Python3

import abc
import time
import datetime
 
class Subject(object):
    def __init__(self):
        self.observers = []
        self.cur_time = None
 
    def register_observer(self, observer):
        if observer in self.observers:
            print(observer, 'already registered')
        else:
            self.observers.append(observer)
 
    def unregister_observer(self, observer):
        try:
            self.observers.remove(observer)
        except ValueError:
            print('Cannot Identify the Observer')
 
    def notify_observer(self):
        self.cur_time = datetime.datetime.now()
         
        for observer in self.observers:
            observer.notify(self.cur_time)
 
class Observer(object, metaclass=abc.ABCMeta):   
    """ Abstract class for Observers """
    @abc.abstractmethod
    def notify(self, unix_timestamp):
        pass
 
 
class CompanyNewsletterObserver(Observer):
    """ Company Newsletter """
    def __init__(self, name):
        self.name = name
 
    def notify(self, time):
        print(self.name, ':', time)
 
class ConsumerNewsletterObserver(Observer):
    """ Consumer Newsletter """
    def __init__(self, name):
        self.name = name
 
    def notify(self, time):
        print(self.name, ':', time)
 
if __name__ == '__main__':
    subject = Subject()
 
    print('Registering company_newsletter_observer')
    cmp_observer = CompanyNewsletterObserver('company_newsletter_observer')
    subject.register_observer(cmp_observer)
    subject.notify_observer()
    print()
    time.sleep(2)
 
    print('Registering consumer_newsletter_observer')
    con_observer = ConsumerNewsletterObserver('consumer_newsletter_observer')
    subject.register_observer(con_observer)
    subject.notify_observer()
    print()
    time.sleep(2)
 
    print('Unregistering company_newsletter_observer')
    subject.unregister_observer(cmp_observer)
    subject.notify_observer()

Producción:

Registering company_newsletter_observer 
company_newsletter_observer : 2020-10-15 20:40:04.335355
Registering consumer_newsletter_observer 
company_newsletter_observer : 2020-10-15 20:40:06.336913 
consumer_newsletter_observer : 2020-10-15 20:40:06.336913
Unregistering company_newsletter_observer 
consumer_newsletter_observer : 2020-10-15 20 :40:08.339662

Puede consultar el resultado anterior para comprender el comportamiento del código al registrar y cancelar el registro de observadores.

Un patrón de diseño de observador se adapta mejor a la necesidad de lograr una relación de uno a muchos. Puede transmitir la misma información a muchos oyentes. Y los oyentes se pueden agregar o eliminar en tiempo de ejecución. Aquí, el sujeto solo tiene información sobre la interfaz del observador, lo que ayuda a mantener un acoplamiento débil entre el sujeto y los observadores.  

Publicación traducida automáticamente

Artículo escrito por SonuGeorge 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 *