Skip to content

Observer Pattern

Posted on:December 6, 2021 at 05:02 PM

According to Wikipedia, observer pattern is defined as:

The observer pattern is a software design pattern in which an object, named the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. The Subject contains a list of observers and it notifies them whenever an event occurs. It all observers to subscribe and unsubscribe. The subject is also called Publisher

The observer is an object which registers itself with the Subject to get notified whenever an event occurs. The observer can also unsubscribe when is no longer interested in further notifications. The observer is also called a Subscriber.

A real-world example of an Observer pattern would be a newspaper company. The newspaper company regularly publishes newspapers and magazines. If anyone wants a newspaper then they can subscribe and as long the subscription is active they will receive the newspaper and when they are no longer interested they can simply unsubscribe.

In this example the publishing company is Subject and the people who have subscriptions are observers.

Lets explore the component of Obersever pattern and later on we will code a concrete example.

First we will create an interface call Subject. The interface will be implemented by the class which wants to acts as a Subject.

interface Subject {
  registerObserver(observer: Observer);
  removeObserver(observer: Observer);
  notifyObservers();
}

The methods in the interface are self explanatory.

Next we will create a interface called Observer. All the classes which wants to listen for events must implement this interface

interface Observer {
  update(value: any);
}

Now lets use these interface in actual implementation. Consider the scenario that you have a weather station which periodically creates weather data. We want to send this data to user display console, log to console and send to alert system.

First we will create a class for WeatherStation as this weather station is Subject it will implement the Subject interface.

class WeatherStation implements Subject {
  private observers: Observer[]
  constructor() {
    this.observer = [];
  }

  registerObserver(observer: Observer) {
    this.observer.push(observer);
  }

  removeObserver(observer: Observer) {
    this.observer = this.observer.filter(obs => obs !== observer);
  }

  notifyObservers(newVal: any) {
    this.observer.forEach(obs => obs.update(newVal))
  }
}

Now lets create UserInterface, as this class is observer it will implement the Observer interface.

class UserInterface implements Observer {

  constructor(private subject: Subject) {
    subject.registerObserver(this);
  }

  updateTheInterface(newValue) {
    // update the user interface
  }

  update(newVal: any) {
    this.updateTheInterface(newVal);
  }
}

Similar to UserInterface class we will create Logger and Alert class


class Logger implements Observer {

  constructor(private subject: Subject) {
    subject.registerObserver(this);
  }

  log(value) {
    // log the value
  }

  update(newVal: any) {
      this.log(newVal);
    }
}

class Alert {

  constructor(private subject: Subject) {
    subject.registerObserver(this);
  }

  soundAlert() {
    // sends alert
  }

  update(newVal: any) {
    if (newVal.windSpeed > 101) {
      this.soundAlert();
    }
  }
}

Putting it all together it will be used like this:

const weatherStation = new WeatherStation();

const alert = new Alert(weatherStation);
const logger = new Logger(weatherStation);
const userInterface = new UserInterface(weatherStation);

Now whenever there is update from the weather station, the update method of all the Observers will be called and they can do their respective operations. You can use observer patten in very powerful ways!