Observer Pattern for Beginners

Vivek Alhat - Dec 3 '23 - - Dev Community

Observer Pattern

The observer pattern is a widely used behavioral design pattern. It allows objects to subscribe and receive updates about events happening in the object they are observing.

Consider an example of an online clothing store. You want a specific hoodie, but it's currently out of stock. You check the site daily to see if it's available. The store offers alerts when the product is back in stock, so you subscribe to receive notifications. This eliminates the need to manually check the store.

Such problems are commonly solved using the observer pattern.

Observer pattern mainly has two things:

  • An observable or a publisher
  • An observer or a subscriber

In the example above, the observable is the product you're looking for and you are the observer.

The key concept behind the observable pattern is loose coupling, the observable and observer don’t need to know specifics of each other. In the above example, you have decoupled yourself from the process of manually checking the store every day, and the store only notifies you when there’s a relevant change.

Mental Model

Below is the mental model behind the observer pattern:

  • Observable
    • This is the object that is being observed.
    • It maintains a list of observers.
    • It provides methods to subscribe, unsubscribe, and notify observers.
  • Observer
    • This is the object that is interested in state changes of the observable.
    • It subscribes to the observable to receive updates.
    • It has an update method that is called by an observable when its state changes.
    • There can be multiple observers.

Code Implementation

Let’s implement this in TypeScript using classes.

First, we will create an observable class called store with the below interface,

interface Observable {
  subscribe(o: Observer): void;
  unsubscribe(o: Observer): void;
  notify(): void;
}
Enter fullscreen mode Exit fullscreen mode

The observable class will have a private message variable of type string and a setMessage method to update the status of the product availability. It will also have an array to maintain a list of observers. Finally, let’s add subscribe, unsubscribe, and notify methods.

Here’s the complete implementation of the observable,

class Store implements Observable {
  private message: string = "";
  private observers: Array<Observer> = [];

  setMessage(message: string) {
    this.message = message;
    this.notify(); // notify all observers when the message state is changed
  }

  subscribe(o: Observer): void {
    this.observers.push(o);
  }

  unsubscribe(o: Observer): void {
    const index = this.observers.indexOf(o);
    this.observers.splice(index, 1);
  }

  notify(): void {
    for (const o of this.observers) {
      o.update(this.message); // call update method of observer with new message
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, let’s create an observer class called user with the below interface,

interface Observer {
  update(notice: string): void;
}
Enter fullscreen mode Exit fullscreen mode

The observer class is going to be simple with only the update method. Below is the complete implementation of an observer,

class User implements Observer {
  private observable: Observable;

  constructor(observable: Observable) {
    this.observable = observable;
    this.observable.subscribe(this); // subscribe automatically when a new User object is created
  }

  update(message: string): void {
    console.log(`Store update : ${message}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

Now when we update the store message using the setMessage function it will notify all the observers of the class.

const store = new Store();
const user = new User(store); // after creation, it observes the store class

// store.subscribe(user) // Another way of subscribing to the observable 

store.setMessage("Hoodie is available now"); // this will call the update method and console log the message
store.unsubscribe(user);
store.setMessage("Autumn sale is live now"); // this message won't be logged as user has unsubscribed from the observable
Enter fullscreen mode Exit fullscreen mode

You can check the code in below replit:

Useful links

Observer Pattern

. . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player