Observer

Buffer this pageShare on FacebookPrint this pageTweet about this on TwitterShare on Google+Share on LinkedInShare on StumbleUpon
Reading Time: 2 minutes

Observer Design Pattern in Python

Observer Design Pattern in Python

Design Patterns Home
 

What is it?

The Observer Design Pattern is exactly what the name suggests. There is a subject (such as Core Temperature in a nuclear plant) which is being observed by multiple observers (Faculty of the Nuclear Plant). The subject needs to be monitored and whenever there is a change in the subject, the observers are be notified about the change.

Consider a scenario where the faculty of a Nuclear Plant need to keep an eye on the core temperature. As soon as the temperature changes, the faculty members need to be notified so that they can initiate necessary control protocol if need be.

It is classified under Behavioural Design Patterns as it offers a popular way to handle communication between objects.


Why the need for it: Problem Statement

The Observer Pattern is employed where there is a subject that needs to be monitored. Any change in the subject notifies its observers who are monitoring it.


Terminology

  1. Subject: A class representing what is being observed. The subject has at least one main attribute (temperature, in this case, with Core being the subject), and the following methods to go with it:
    • __init__: initializes an empty list of observers; initializes local variables with passed values; initializes the key attribute.
    • attach(): appends the passed observer to the list of observers.
    • detach(): removes the passed observer from the list of observers.
    • notify(): notifies each observer about the change in the value of attribute by calling their update() method.
    • attribute setter(): calls the notify() method each time a new value is set to the attribute.
  2. Observer: A class whose objects keep an eye on the subject. It has the following method, among other methods:
    • update(): it is the alert method which is invoked when the notify() in the subject is invoked.

Pseduo Code

class Core:
        '''Represents what is being observed.'''
        def __init__(name):
                '''Initialized an empty list of observers; Set the name of the core; initialize its temperature.'''

        def attach(observer):
                '''If the observer is not already in the observers list; append the observer to the list'''

        def detach(observer):
                '''Remove the observer from the list of observers.'''

        def notify():
                '''Alert all observers.'''

        def temp(temp):
                '''Notify the observers whenever somebody changes the core temperature'''
                
class FacultyMonitoringCore:
        '''Observer: Monitoring the subject.'''
        def update(subject):
                '''Alert method invoked when the notify() method in the subject is invoked.'''

## USING THE ABOVE PATTERN ##
Create a subject to be monitored
Create observers
Attach the observers to the subject
Changing the temperature of the core, and see if every observer is being notified or not.

How to implement it

class Core:
        '''Represents what is being observed.'''
        def __init__(self, name):
                '''Initialized an empty list of observers; Set the name of the core; initialize its temperature.'''
                self._observers = []
                self._name = name
                self._temp = 0

        def attach(self, observer):
                '''If the observer is not already in the observers list; append the observer to the list'''
                if observer not in self._observers: 
                        self._observers.append(observer)
        def detach(self, observer):
                '''Remove the observer from the list of observers.'''
                try:
                        self._observers.remove(observer)
                except ValueError:
                        print("Observer is already not in the list of observers.")
        def notify(self):
                '''Alert all observers.'''
                for observer in self._observers: 
                        observer.update(self)
                
        # Getter that gets the temperature of core
        @property
        def temp(self):
                '''The @property decorator makes a property object 'temp', on which a setter can be defined, as done below.'''
                return self._temp

        #Setter that sets the temperature of core
        @temp.setter
        def temp(self, temp):
                '''Notify the observers whenever somebody changes the core temperature.
                   @temp.setter notation signifies the setter method of the temp property which
                   allows to set the temperature using the assignment operator i.e. objectOfCore.temp = 300
				   sets the temp attribute to 50'''
                self._temp = temp
                self.notify()
                
class FacultyMonitoringCore:
        '''Observer: Monitoring the subject.'''
        def update(self, subject):
                '''Alert method invoked when the notify() method in the subject is invoked.'''
                if subject._temp > 350:
                    print("FacultyMonitoringCore says: {} has temperature {}. Code Red!!!".format(subject._name, subject._temp))
                else:
                    print("FacultyMonitoringCore says: {} has temperature {}. Everything is under control.".format(subject._name, subject._temp))

# Create a subject to be monitored
coreOne = Core("Core 1")

# Create observers
facultyMonitoringCoreOne = FacultyMonitoringCore()
facultyMonitoringCoreTwo = FacultyMonitoringCore()

# Attach the observers to the subject
coreOne.attach(facultyMonitoringCoreOne)
coreOne.attach(facultyMonitoringCoreTwo)

# Changing the temperature of the core, which invokes the notify() method of class Core, which in turn invokes the update() method of each observer.
coreOne.temp = 300
coreOne.temp = 360

## OUTPUT ##
FacultyMonitoringCore says: Core 1 has temperature 300. Everything is under control.
FacultyMonitoringCore says: Core 1 has temperature 300. Everything is under control.
FacultyMonitoringCore says: Core 1 has temperature 360. Code Red!!!
FacultyMonitoringCore says: Core 1 has temperature 360. Code Red!!!

Walkthrough of implementation

  1. We first create an object of our Subject i.e. Core (coreOne = Core("Core 1")).
  2. Then, we create a couple of observers (facultyMonitoringCoreOne = FacultyMonitoringCore()).
  3. Then, we attach the observers to the object of the Subject (coreOne.attach(facultyMonitoringCoreOne)).
  4. Finally, we change the temperature of the Subject object (coreOne.temp = 300), which invokes the temp() method which further invokes the notify() method of class Core, which in turn invokes the update() method of each observer.

Further scope of code used here:

The code above is a basic implementation of the Observer Pattern. It can extended to incorporate following changes:

  1. Make the class Subject an abstract class and have the Core class inherit it.
  2. Add a name attribute to the FacultyMonitoringCore class, so that it becomes clear as to which object of this class is restating the temperature in the update() method.
  3. Alert everyone except the entity which is setting the temperature.

More on property object:

You can read more about property objects here.


Related to: Singleton


 

 

 

 


See also:

Buffer this pageShare on FacebookPrint this pageTweet about this on TwitterShare on Google+Share on LinkedInShare on StumbleUpon

Leave a Reply