DEV Community

Vivek Alhat
Vivek Alhat

Posted on

Observer Pattern for Beginners

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

Top comments (5)

Collapse
 
joolsmcfly profile image
Julien Dephix

Hi. Nice post!

There are couple of things I'd change so your implementation matches requirements a bit closer.

You mention a store and users that want to get notified of stock changes for a hoodie but code only shows the store implementation.
I'd expect to be able to subscribe to a product, not to a store directly.

And, unless I am mistaken, your implementation only allows a user to subscribe to one product (you're binding a user to one observable in the constructor).

I'd code it so you have a store with a list of products. Users can then subscribe to one or more products via product.subscribe(user) or, user.subscribe(product).

user's update method would get a Product as argument so it knows what product has changed (name, quantity, price etc).

Hope this helps!

Collapse
 
vivekalhat profile image
Vivek Alhat

I agree with your points. The current implementation indeed focuses on the store as the observable, but in a more realistic scenario, allowing users to subscribe to specific products makes a lot of sense. It provides a more fine-grained approach to notifications, and users should have the flexibility to choose the products they are interested in.
Thanks for taking the time to share your thoughts!

Collapse
 
m0n0x41d profile image
Ivan Zakutnii

Please, write about Visitor!

Collapse
 
vivekalhat profile image
Vivek Alhat

Sure! Will do.

Collapse
 
m0n0x41d profile image
Ivan Zakutnii

Thank you! Then I'll follow you and wait for it, my friend :3