Python notes: observer mode

Keywords: Python

In the observer pattern, the subject object generally has a core service that other services depend on, and maintains a list of other objects that depend on this core service (that is, the list of observers or monitors). When the subject object changes, the observer should change his or her state or perform some operations

Three roles in the observer pattern:

  • Subject: that is, the object observed by the observer. Generally, there are registration and cancellation methods to add and delete the observer.
  • Observer base class: this class is mainly to define an interface so that the corresponding notification information can be obtained when the subject changes.
  • Observer: this class needs to implement the "notification" interface in the base class to keep pace with changes in the topic.

There are two ways to notify the subject:

  • Pull model: this method focuses on the observer. When the subject changes, all observers will be broadcast, and then the observer will obtain the corresponding data.
  • Push model: this method focuses on the theme. When the theme changes, the theme will push its own changes to the required observer according to the needs of the observer.

Advantages of observer mode:

  • Objects interacting with each other in the observer pattern are loosely coupled. The only understanding of the subject to the observer is the "notification" interface implemented by the observer. In addition, they are independent of each other and can be modified as needed.
  • You can add or remove observers at any time.
  • In this mode, efficient data transmission between objects can be performed with little or no modification of the subject or observer.

Other notes:

  • In the observer pattern, there can be multiple themes and corresponding relationships between multiple observers, but it is necessary to make clear the relationship and changes between them, otherwise it will become very complex.
  • In general, the subject triggers the notification method, but in special cases, the observer can also trigger the notification method.

Simple example:

from abc import ABCMeta, abstractmethod


class Publisher:
    """Observed: release/Publishing objects in a subscription relationship"""
    def __init__(self):
        self.subscribers = []
        self.latest_content = None

    def set_content(self, content):
        """Publish new news when there is new news"""
        self.latest_content = content
        self.publish()

    def get_latest_content(self):
        """Get the latest news"""
        return self.latest_content

    def register(self, subscriber):
        """Register a new subscriber"""
        self.subscribers.append(subscriber)

    def publish(self):
        """Publish messages and notify subscribers"""
        for subscriber in self.subscribers:
            subscriber.notify()


class Subscriber(metaclass=ABCMeta):
    """Observer's abstract class: a notification interface needs to be defined for users who publish object notification subscriptions"""
    @abstractmethod
    def notify(self):
        pass


class SubscriberA(Subscriber):
    """Observer A: Release/Subscribers in a subscription relationship can receive timely notifications when there are new changes or developments in the subscribers' Publishers"""
    def __init__(self):
        self.my_publisher = None

    def subscribe(self, publisher):
        """Subscribe and register"""
        self.my_publisher = publisher
        self.my_publisher.register(self)

    def notify(self):
        """Get the latest news"""
        latest_content = self.my_publisher.get_latest_content()
        print(self, latest_content)


class SubscriberB(Subscriber):
    """Observer B: Release/Subscribers in a subscription relationship can receive timely notifications when there are new changes or developments in the subscribers' Publishers"""
    def __init__(self):
        self.my_publisher = None

    def subscribe(self, publisher):
        """Subscribe and register"""
        self.my_publisher = publisher
        self.my_publisher.register(self)

    def notify(self):
        """Get the latest news"""
        latest_content = self.my_publisher.get_latest_content()
        print(self, latest_content)


if __name__ == '__main__':
    new_publisher = Publisher()
    subscriber_a = SubscriberA()
    subscriber_a.subscribe(new_publisher)
    subscriber_b = SubscriberB()
    subscriber_b.subscribe(new_publisher)
    new_publisher.set_content('This is a new message!')

Posted by fnairb on Tue, 19 Nov 2019 11:42:17 -0800