Understanding Design Patterns: Observer
Tags: javascript, designpatterns, cleancode, typescript
Published: 2021-04-27 22:19:13

---
title: Understanding Design Patterns: Observer
published: true
description: In this article, I am going to describe how the **Observer Pattern** works and when it should be applied.
tags: javascript, designpatterns, cleancode, typescript
cover_image: https://cdn-images-1.medium.com/max/800/1*1A5PQy5B8XFx7den3vbrBg.jpeg
canonical_url: https://www.carloscaballero.io/understanding-design-patters-observer
series: pattern-design
---

There are 23 classic design patterns which are described in the original book Design Patterns: Elements of Reusable Object-Oriented Software. These patterns provide solutions to particular problems often repeated in software development.

In this article, I am going to describe how the **Observer Pattern** works and when it should be applied.

---

# Observer Pattern: Basic Idea
Wikipedia provides us with the following definition:

>  The **observer pattern** is a [software design pattern](https://en.wikipedia.org/wiki/Design_pattern_(computer_science)) in which an [object](https://en.wikipedia.org/wiki/Object_(computer_science)#Objects_in_object-oriented_programming), 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](https://en.wikipedia.org/wiki/Method_(computer_science)). — [Wikipedia](https://en.wikipedia.org/wiki/Observer_pattern)

On the other hand, the definition provided by the original book is the following:

>  Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. — Design Patterns: Elements of Reusable Object-Oriented Software

On many occasions we need to communicate system objects without coupling them either at code or at communication mechanism level. Should we have a group of objects (observers) that are required to be aware of the state of another object (observable), there are different techniques for carrying out  the communication between them. The most popular techniques are:

 1. **Busy waiting**. A process repeatedly verifies a condition. In our case, it would be an observer constantly checking whether or not the observable's condition has changed. This strategy could be a valid solution in certain cases, but it isn't an adequate solution for our scenario, since it would imply having several processes (observers) consuming resources without performing any operations, causing an exponential performance decrease in the number of existing observers.


 2. ***Polling***. In this case, the query operation is performed with a small window of time between operations. This is an attempt to implement synchronism between processes. However, we can once again appreciate degradation in the system's performance, furthermore, depending on the time set between each query, the information can be so delayed that it might be invalid causing a wastage of resources used by this technique.

The following codes show implementations of the previous techniques:

**Busy-Waiting:**

```javascript
while(!condition){
   // Query
   if(isQueryValid) condition = true;
}
```

**Polling:**
```javascript
function refresh() {
    setTimeout(refresh, 5000);
    // Query
}

// initial call, or just call refresh directly
setTimeout(refresh, 5000);
```

Although it isn't the goal of this post, it's a good idea to understand the two alternative techniques to this design pattern. Therefore, we can say that, in a nutshell, the difference between the active wait and polling techniques is that in the former the query operation is performed all the time, while in the latter there are intervals of time where the operation isn't executed.

**Busy-Waiting:**

```javascript
while(resourceIsNotReady()){
  //Do nothing
}
```

***Polling*:**
```javascript
while(resourceIsNotReady()){
     Sleep(1000); // 1000 or anytime
 }
```

The **Observer** pattern allows us to achieve a more efficient and less coupled code, since it avoids the previously mentioned issue, as well as having other advantages regarding code maintainibility. The UML pattern of this pattern is the following:

![UML diagram of the book Design Patterns: Elements of Reusable Object-Oriented Software.](https://cdn-images-1.medium.com/max/2000/1*Dk6aMlxBYXBPdFq4Ftxi2A.gif)

The classes that comprise this pattern are the following:

* **Subject** is the interface that every **observed** class implements. This interface contains the `attach` and `detach` methods that allow us to add and remove observers from the class. It also contains a `notify` method, which is responsible for notifying all of the observers that a change has occurred in the observed. Also, all of the `subject`s store references of the objects that observe them (`observers`).
 
* **Observer** is the interface that all of the `ConcreteObserver`s implement. In this interface, the `update` method is defined, which contains the business logic to be executed by each observer upon receiving the change notification from the `Subject`.

* **ConcreteSubject** is the concrete implementation of the `Subject` class. 
This class defines the state of the `SubjectState` application, which must be notified when a change occurs. For this reason, the accessor methods (`getState` and `setState`) are usually implemented, since they manipulate the state. This class is also responsible for sending the notification to all of its observers when the state changes.

* **ConcreteObserver** is the class that models each of the concrete observers. In this class the `update` method belonging to the `Observer` interface is implemented, which is responsible for maintaining its state consistently which is responsible for keeping its state consistent with the `subject` objects it is observing.

Nowadays there's a family of libraries known as [***Reactive Extensions or ReactiveX***](https://en.wikipedia.org/wiki/ReactiveX) which have made this design pattern popular. The *Reactive Extensions* make use of two design patterns: 1) Observer 2) [Iterator](https://medium.com/better-programming/understanding-the-iterator-pattern-in-javascript-typescript-using-symbol-iterator-ab400d46b14a). They also have a group of operators that use functional programming. These are some of the most popular *Reactive Exntensions*:

* Java: [RxJava](https://github.com/ReactiveX/RxJava)

* JavaScript: [RxJS](https://github.com/ReactiveX/rxjs)

* C#: [Rx.NET](https://github.com/Reactive-Extensions/Rx.NET)

* C#(Unity): [UniRx](https://github.com/neuecc/UniRx)

In these implementations, there are differences in the naming of classes and methods. The following names are the most extended:

 1. `Subscriber` corresponds with the class `Observer`.

 2. `ConcreteSubscribers` correspond with the classes `ConcreteObservers`.

 3. The `Subject` class is maintained. The `attach` and `detach` methods are renamed to `subscribe` and `unsubscribe`.

 4. The `ConcreteSubjects` classes are concrete implementations, like `BehaviorSubject`, `ReplaySubject` o `AsyncSubject`. 

---

# Observer Pattern: Communication Strategies

There are two communication strategies between `Subject`s (observables) and  `Observer`s (observadores) in the observer pattern:

* **Pull**. In this model, the `subject` sends the minimum information to the observers and they are responsible for making inquiries to obtain more detail. This model focuses on the fact that the `Subject` ignores the `observers`. 

* **Push**. In this model, the `subject` sends the greatest amount of information to the `observers` the information of the change produced, regardless of whether they wanted it or not. In this model, the `Subject` knows in depth the needs of each of its `observers`.
 

Although a priori it may seem that the *push* communication technique is less reusable due to the fact that the `Subject` must have knowledge about the `observers`, this is not always the case. On the other hand, the *pull* based communication technique can be inefficient because the `observers` have to figure out what changed without help from the `Subject`.

---

# Observer Pattern: When To Use

1. When there is a one-to-many dependency between system objects so that when the object changes state, all dependent objects need to be notified automatically.

2. You do not want to use [busy-waiting] (https://en.wikipedia.org/wiki/Busy_waiting) and [Polling] (https://en.wikipedia.org/wiki/Polling_(computer_science)) to update observers.

3. Decouple the dependencies between the `Subject` objects (Observables) and the `Observers` (Observers) allowing to respect the *Open-Closed Principle*.


---

# Observer Pattern: Advantages and Disadvantages
The *Observer* pattern has a number of advantages that can be summarized in the following points:

* The code is more maintainable because it is less coupled between the *observable* classes and their dependencies (the *observers*).

* **Clean code** since the *Open-Closed Principle* is guaranteed due to the new observers (subscribers) can be introduced without breaking the existing code in the observable (and vice versa).

* **Cleaner code** because the *Single Responsibility Principle (SRP)* is respected since the responsibility of each observer is transferred to its `update` method instead of having that business logic in the Observable object.

* Relationships between objects can be established at runtime rather than at compile time.

However, the main drawback of the *observer* pattern, like most design patterns, is that there is an increase in complexity in the code, and an increase in the number of classes required for the code. Although, this disadvantage is well known when applying design patterns since the price to pay for gaining abstraction in the code.


---

# Observer Pattern Examples

Next, we are going to illustrate two examples of application of the *Observer* pattern:

1. Basic structure of the *Observer* pattern. In this example we are going to translate the theoretical UML diagram into TypeScript code to identify each of the classes involved in the pattern.

2. An auction system in which there is an object (`subject`) that emits the change produced (`push` technique) in the `price` of a `product` that is being auctioned to all observers (`observer`) interested in acquiring that `product`. Every time the `price` of the `product` auction increases because some observer has increased the bid, it is notified to all observers.

The following examples will show the implementation of this pattern using **TypeScript**. We have chosen TypeScript to carry out this implementation rather than JavaScript — the latter lacks interfaces or abstract classes so the responsibility of implementing both the interface and the abstract class would fall on the developer.

---

## Example 1: Basic structure of the observer pattern

In this first example, we're going to translate the theoretical UML diagram into TypeScript to test the potential of this pattern. This is the diagram to be implemented:

![UML diagram of the book Design Patterns: Elements of Reusable Object-Oriented Software.](https://cdn-images-1.medium.com/max/2000/1*qNlF1YbirVKOjCaIGgihnQ.jpeg)

First, we are going to define the interface (`Subject`) of our problem. Being an interface, all the methods that must be implemented in all the specific `Subject` are defined, in our case there is only one `ConcreteSubject`. The `Subject` interface defines the three methods necessary to comply with this pattern: `attach`, `detach` and `notify`. The `attach` and `detach` methods receive the `observer` as a parameter that will be added or removed in the `Subject` data structure.


```javascript
import { Observer } from "./observer.interface";

export interface Subject {
  attach(observer: Observer): void;
  detach(observer: Observer): void;
  notify(): void;
}
```

There can be as many `ConcreteSubject` as we need in our problem. As this problem is the basic scheme of the *Observer* pattern, we only need a single `ConcreteSubject`. In this first problem, the state that is observed is the state attribute, which is of type number. On the other hand, all `observers` are stored in an array called `observers`. The `attach` and `detach` methods check whether or not the `observer` is previously in the data structure to add or remove it from it. Finally, the `notify` method is in charge of invoking the `update` method of all the `observers` that are observing the `Subject`.

Objects of the `ConcreteSubject` class perform some task related to the specific business logic of each problem. In this example, there is a method called `operation` that is in charge of modifying the `state` and invoking the `notify` method.


```javascript
import { Observer } from "./observer.interface";
import { Subject } from "./subject.interface";

export class ConcreteSubject implements Subject {
  public state: number;
  private observers: Observer[] = [];

  public attach(observer: Observer): void {
    const isAttached = this.observers.includes(observer);
    if (isAttached) {
      return console.log("Subject: Observer has been attached already");
    }

    console.log("Subject: Attached an observer.");
    this.observers.push(observer);
  }

  public detach(observer: Observer): void {
    const observerIndex = this.observers.indexOf(observer);
    if (observerIndex === -1) {
      return console.log("Subject: Nonexistent observer");
    }

    this.observers.splice(observerIndex, 1);
    console.log("Subject: Detached an observer");
  }

  public notify(): void {
    console.log("Subject: Notifying observers...");
    for (const observer of this.observers) {
      observer.update(this);
    }
  }

  public operation(): void {
    console.log("Subject: Business Logic.");
    this.state = Math.floor(Math.random() * (10 + 1));

    console.log(`Subject: The state has just changed to: ${this.state}`);
    this.notify();
  }
}
```

The other piece of this design pattern is the `observer`. Therefore, let's start by defining the `Observer` interface which only needs to define the `update` method which is in charge of executing every time an `observer` is notified that a change has occurred.


```javascript
import { Subject } from "./subject.interface";

export interface Observer {
  update(subject: Subject): void;
}
```

Each class that implements this interface must include its business logic in  the `update` method. In this example two `ConcreteObserver`s have been defined, which will perform actions according to the `Subject`s state. The following code shows two concrete implementations for two different types of observers: `ConcreteObserverA` and `ConcreteObserverB`.

```javascript
import { ConcreteSubject } from "./concrete-subject";
import { Observer } from "./observer.interface";
import { Subject } from "./subject.interface";

export class ConcreteObserverA implements Observer {
  public update(subject: Subject): void {
    if (subject instanceof ConcreteSubject && subject.state < 3) {
      console.log("ConcreteObserverA: Reacted to the event.");
    }
  }
}
```

```javascript
import { ConcreteSubject } from "./concrete-subject";
import { Observer } from "./observer.interface";
import { Subject } from "./subject.interface";

export class ConcreteObserverB implements Observer {
  public update(subject: Subject): void {
    if (
      subject instanceof ConcreteSubject &&
      (subject.state === 0 || subject.state >= 2)
    ) {
      console.log("ConcreteObserverB: Reacted to the event.");
    }
  }
}
```

Finally, we define our `Client` or `Context` class, which makes use of this pattern. In the following code the necessary classes to simulate the use of `Subject` and `Observer` are implemented:

```javascript
import { ConcreteObserverA } from "./concrete-observerA";
import { ConcreteObserverB } from "./concrete-observerB";
import { ConcreteSubject } from "./concrete-subject";

const subject = new ConcreteSubject();

const observer1 = new ConcreteObserverA();
subject.attach(observer1);

const observer2 = new ConcreteObserverB();
subject.attach(observer2);

subject.operation();
subject.operation();

subject.detach(observer2);

subject.operation();
```

---

## Example 2 — Auctions using Observer

In this example we're going to use the *Observer* pattern to simulate an action house in which a group of auctioneers (`Auctioneer`) bid for different products (`product`). The auction is directed by an agent (`Agent`). All of our auctioneers need to be notified each time one of them increases their bid, so that they can decide whether to continue bidding or to retire.

Like we did in the previous example, let's begin by taking a look at the UML diagram that is going to help us identify each of the parts that this pattern is composed of.

![Observer pattern](https://cdn-images-1.medium.com/max/2402/1*4EraBmYxYAQlQH_PRXb7VA.jpeg)

The `product` that is being auctioned is the `Subject`'s state, and all of the `observer`s await notifications whenever it changes. Therefore, the `product` class is comprised of three attributes: `price`, `name` and `auctioneer` (the auctioneer that is assigned the product).

```javascript
import { Auctioneer } from "./auctioneer.interface";

export class Product {
  public price;
  public name;
  public auctionner: Auctioneer = null;

  constructor(product) {
    this.price = product.price || 10;
    this.name = product.name || "Unknown";
  }
}
```

The `Agent` is the interface that defines the methods for managing the group of  `Auctioneer`s, and notifying them that the bid on the auctioned product has changed. In this case, the `attach` and `detach` methods have been renamed to `subscribe` and `unsubscribe`.

```javascript
import { Auctioneer } from "./auctioneer.interface";

export interface Agent {
  subscribe(auctioneer: Auctioneer): void;
  unsubscribe(auctioneer: Auctioneer): void;
  notify(): void;
}
```

The concrete implementation of the `Agent` interface is performed by the `ConcreteAgent` class. As well as the three methods previously described, which have a very similar behavior to the one presented in the previous example, the `bidUp` method has been implemented, which, after making some checks on the auctioneer's bid, assigns it as valid and notifies all of the auctioneers of the change.

```javascript
import { Agent } from "./agent.interface";
import { Auctioneer } from "./auctioneer.interface";
import { Product } from "./product.model";

export class ConcreteAgent implements Agent {
  public product: Product;
  private auctioneers: Auctioneer[] = [];

  public subscribe(auctioneer: Auctioneer): void {
    const isExist = this.auctioneers.includes(auctioneer);
    if (isExist) {
      return console.log("Agent: Auctioneer has been attached already.");
    }

    console.log("Agent: Attached an auctioneer.");
    this.auctioneers.push(auctioneer);
  }

  public unsubscribe(auctioneer: Auctioneer): void {
    const auctioneerIndex = this.auctioneers.indexOf(auctioneer);
    if (auctioneerIndex === -1) {
      return console.log("Agent: Nonexistent auctioneer.");
    }

    this.auctioneers.splice(auctioneerIndex, 1);
    console.log("Agent: Detached an auctioneer.");
  }

  public notify(): void {
    console.log("Agent: Notifying auctioneer...");
    for (const auctioneer of this.auctioneers) {
      auctioneer.update(this);
    }
  }

  public bidUp(auctioneer: Auctioneer, bid: number): void {
    console.log("Agent: I'm doing something important.");
    const isExist = this.auctioneers.includes(auctioneer);
    if (!isExist) {
      return console.log("Agent: Auctioneer there is not in the system.");
    }
    if (this.product.price >= bid) {
      console.log("bid", bid);
      console.log("price", this.product.price);
      return console.log(`Agent: ${auctioneer.name}, your bid is not valid`);
    }
    this.product.price = bid;
    this.product.auctionner = auctioneer;

    console.log(
      `Agent: The new price is ${bid} and the new owner is ${auctioneer.name}`
    );
    this.notify();
  }
}
```

In this problem there are four different types of `Auctioneer` defined in the `AuctioneerA`, `AuctioneerB`, `AuctioneerC` and `AuctioneerD` classes. All of these auctioneers implement the `Auctioneer` interface, which defines the `name`, `MAX_LIMIT` and the `update` method. The `MAX_LIMIT` attribute defines the maximum amount that can be bid by each type of `Auctioneer`.

```javascript
import { Agent } from "./agent.interface";

export interface Auctioneer {
  name: string;
  MAX_LIMIT: number;
  update(agent: Agent): void;
}
```

The different types of `Auctioneer` have been defined, to illustrate that each one will have a different behavior upon receiving the `Agent`s notification in the `update` method. Nevertheless, all that has been modified in this example is the probability of continuing to bid and the amount they increase their bids by.


```javascript
import { Agent } from "./agent.interface";
import { Auctioneer } from "./auctioneer.interface";
import { ConcreteAgent } from "./concrete-agent";

export class ConcreteAuctioneerA implements Auctioneer {
  name = "ConcreteAuctioneerA";
  MAX_LIMIT = 100;

  public update(agent: Agent): void {
    if (!(agent instanceof ConcreteAgent)) {
      throw new Error("ERROR: Agent is not a ConcreteAgent");
    }

    if (agent.product.auctionner === this) {
      return console.log(`${this.name}: I'm the owner... I'm waiting`);
    }

    console.log(`${this.name}: I am not the owner... I'm thinking`);
    const bid = Math.round(agent.product.price * 1.1);
    if (bid > this.MAX_LIMIT) {
      return console.log(`${this.name}: The bid is higher than my limit.`);
    }
    agent.bidUp(this, bid);
  }
}
```

```javascript
import { Agent } from "./agent.interface";
import { Auctioneer } from "./auctioneer.interface";
import { ConcreteAgent } from "./concrete-agent";

export class ConcreteAuctioneerB implements Auctioneer {
  name = "ConcreteAuctioneerB";
  MAX_LIMIT = 200;

  public update(agent: Agent): void {
    if (!(agent instanceof ConcreteAgent)) {
      throw new Error("ERROR: Agent is not a ConcreteAgent");
    }

    if (agent.product.auctionner === this) {
      return console.log(`${this.name}: I'm the owner... I'm waiting`);
    }

    console.log(`${this.name}: I am not the owner... I'm thinking`);
    const isBid = Math.random() < 0.5;
    if (!isBid) {
      return console.log(`${this.name}: I give up!`);
    }
    const bid = Math.round(agent.product.price * 1.05);
    if (bid > this.MAX_LIMIT) {
      return console.log(`${this.name}: The bid is higher than my limit.`);
    }
    agent.bidUp(this, bid);
  }
}
```

```javascript
import { Agent } from "./agent.interface";
import { Auctioneer } from "./auctioneer.interface";
import { ConcreteAgent } from "./concrete-agent";

export class ConcreteAuctioneerC implements Auctioneer {
  name = "ConcreteAuctioneerC";
  MAX_LIMIT = 500;

  public update(agent: Agent): void {
    if (!(agent instanceof ConcreteAgent)) {
      throw new Error("ERROR: Agent is not a ConcreteAgent");
    }

    if (agent.product.auctionner === this) {
      return console.log(`${this.name}: I'm the owner... I'm waiting`);
    }

    console.log(`${this.name}: I am not the owner... I'm thinking`);
    const isBid = Math.random() < 0.2;
    if (!isBid) {
      return console.log(`${this.name}: I give up!`);
    }
    const bid = Math.round(agent.product.price * 1.3);
    if (bid > this.MAX_LIMIT) {
      return console.log(`${this.name}: The bid is higher than my limit.`);
    }
    agent.bidUp(this, bid);
  }
}
```

```javascript
import { Agent } from "./agent.interface";
import { Auctioneer } from "./auctioneer.interface";
import { ConcreteAgent } from "./concrete-agent";

export class ConcreteAuctioneerD implements Auctioneer {
  name = "ConcreteAuctioneerD";
  MAX_LIMIT = 1000;

  public update(agent: Agent): void {
    if (!(agent instanceof ConcreteAgent)) {
      throw new Error("ERROR: Agent is not a ConcreteAgent");
    }

    if (agent.product.auctionner === this) {
      return console.log(`${this.name}: I'm the owner... I'm waiting`);
    }

    console.log(`${this.name}: I am not the owner... I'm thinking`);
    const isBid = Math.random() < 0.8;
    if (!isBid) {
      return console.log(`${this.name}: I give up!`);
    }
    const bid = Math.round(agent.product.price * 1.2);
    if (bid > this.MAX_LIMIT) {
      return console.log(`${this.name}: The bid is higher than my limit.`);
    }
    agent.bidUp(this, bid);
  }
}
```

Finally, let's show the `Client` class, which makes use of the *observer* pattern. In this example, an auction house is declared, with an `Agent` and four `Auctioneer`s, where two different products (`diamond` and `gem`) are being auctioned. In the first auction, all four auctioneers participate. In the second auction, the `D` class auctioneer retires leaving the three remaining to participate.

```javascript
import { ConcreteAgent } from "./concrete-agent";
import { ConcreteAuctioneerA } from "./concrete-auctioneerA";
import { ConcreteAuctioneerB } from "./concrete-auctioneerB";
import { ConcreteAuctioneerC } from "./concrete-auctioneerC";
import { ConcreteAuctioneerD } from "./concrete-auctioneerD";
import { Product } from "./product.model";

const concreteAgent = new ConcreteAgent();

const auctioneerA = new ConcreteAuctioneerA();
const auctioneerB = new ConcreteAuctioneerB();
const auctioneerC = new ConcreteAuctioneerC();
const auctioneerD = new ConcreteAuctioneerD();

concreteAgent.subscribe(auctioneerA);
concreteAgent.subscribe(auctioneerB);
concreteAgent.subscribe(auctioneerC);
concreteAgent.subscribe(auctioneerD);

const diamond = new Product({ name: "Diamond", price: 5 });
concreteAgent.product = diamond;

concreteAgent.bidUp(auctioneerA, 10);

console.log("--------- new Bid-----------");

concreteAgent.unsubscribe(auctioneerD);

const gem = new Product({ name: "Gem", price: 3 });
concreteAgent.product = gem;

concreteAgent.bidUp(auctioneerB, 5);

console.log(`The winner of the bid is 
             Product: ${diamond.name}
             Name: ${diamond.auctionner.name}
             Price: ${diamond.price}`);

console.log(`The winner of the bid is 
             Product: ${gem.name}
             Name: ${gem.auctionner.name}
             Price: ${gem.price}`);
```

Finally, I've created `two npm scripts`, through which the code presented in this article can be executed:

```javascript
npm run example1
npm run example2
```

GitHub Repo available [here.](https://github.com/Caballerog/blog/tree/master/observer-pattern)


---

# Conclusion

***Observer*** is a design pattern that allows respecting the *Open-Closed Principle* since new `Subject` and `Observer` can be created without breaking the existing code. In addition, it allows communication between two actors of the system without the need for them to be linked in the knowledge of each other. Finally, the performance degradation that occurs in more elementary techniques such as busy-waiting and polling is overcome.


Finally, the most important thing about this pattern is not the concrete implementation of it, but being able to recognize the problem that this pattern can solve, and when it can be applied. The specific implementation is the least of it, since it will vary depending on the programming language used.