Observer Pattern for Beginners
Tags: javascript, typescript, programming, beginners
Published: 2023-12-03 17:48:58

## 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,

```tsx
interface Observable {
  subscribe(o: Observer): void;
  unsubscribe(o: Observer): void;
  notify(): void;
}
```

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,

```tsx
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
    }
  }
}
```

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

```tsx
interface Observer {
  update(notice: string): void;
}
```

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

```tsx
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}`);
  }
}
```

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

```tsx
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
```

You can check the code in below replit:

 {% replit @vivekalhat14/ObserverPattern#index.ts %}

### Useful links
[Observer Pattern](https://refactoring.guru/design-patterns/observer)