---
description: >-
  Source:
  https://levelup.gitconnected.com/design-patterns-in-modern-javascript-development-ec84d8be06ca
  https://medium.com/beginners-guide-to-mobile-web-development/javascript-design-patterns-25f0faaaa
---

# Patterns

## Categories of Design Patterns

### **1. Creational**

For handling **object creational mechanisms**. Solves a problem by controlling the creation process of an object.

Patterns:

1. **Constructor Pattern**
2. **Factory Pattern**
3. **Prototype Pattern**
4. **Singleton Pattern**

### **2. Structural**

Concerned with **class and object composition**. Structure or restructure one or more parts without affecting the entire system. Ie., they help obtain new functionalities without tampering with the existing ones.

Patterns: 

1. **Adapter Pattern**
2. **Composite Pattern**
3. **Decorator Pattern**
4. **Facade Pattern**
5. **Flyweight Pattern**
6. **Proxy Pattern.**

### **3. Behavioral**

**Improvecommunication between dissimilar objects**.

Patterns:

1. **Chain of Responsibility Pattern**
2. **Command Pattern**
3. **Iterator Pattern**
4. **Mediator Pattern**
5. **Observer Pattern**
6. **State Pattern**
7. **Strategy Pattern**
8. **Template Pattern.**

## 1. Design patterns

**General reusable solution to a commonly occurring problem in software design.**

## Singleton pattern

Limit the instantiation of a class to a single object. The first time an object of a class implementing the singleton pattern should be instantiated, it is actually going to get instantiated. Any subsequent try is just going to return that first instance.

### Use case

Instantiating configuration objects (you probably only want one configuration instance for your application)

## Observer pattern

An object, called 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.

In JS terms, you wouldn’t be looping and asking for the result until you run a function any more. You would, instead, let a subject know that you are interested in events (messages) and would provide a callback function which should be called when new data is ready. You are, then, the observer. Multiple observers can subscribe to the subject.

Multiple observers can subscribe to the subject.

### Use cases

When you want to create a one-to-many dependency between objects which isn’t tightly coupled and have the possibility to let an open-ended number of objects know when a state has changed.

**JS is great for the observable pattern because everything is event-driven** and, rather than always asking if an event happened, you should **let the event inform you.** Adding an event listener to an element has all the markings of the observer pattern:

* you can **subscribe** to the object,
* you can **unsubscribe** from the object,
* the **object can broadcast an event to all its subscribers**.

## Facade pattern

Hides the underlying complexity behind a front, effectively allowing you to work with an API which is easier to grasp while providing the possibility to change the underlying code however you want.

## Based on article:

&#x20;[https://medium.com/beginners-guide-to-mobile-web-development/javascript-design-patterns-25f0faaaa15](https://medium.com/beginners-guide-to-mobile-web-development/javascript-design-patterns-25f0faaaa15)

## Constructor pattern&#x20;

**Class-based creational design pattern**.

Constructors are special functions that can be used to instantiate new objects with methods and properties defined by that function.

**It is not one of the classic design patterns. It is more of a basic language construct** than a pattern in most object-oriented languages. But in JS, objects can be created on the fly without any constructor functions or “class” definition.

Used **for creating new objects of a given kind**.

**Example**: define a `Hero` class with attributes like `name` and `specialAbility` and method like `getDetails`. Then, instantiate an object `IronMan` by invoking the constructor method with the `new` keyword passing in the values for the respective attributes as arguments.

{% code title="Constructor.js" %}
```javascript
// traditional Function-based syntax
function Hero(name, specialAbility) {
  // setting property values
  this.name = name;
  this.specialAbility = specialAbility;

  // declaring a method on the object
  this.getDetails = function() {
    return this.name + ' can ' + this.specialAbility;
  };
}

// ES6 Class syntax
class Hero {
  constructor(name, specialAbility) {
    // setting property values
    this._name = name;
    this._specialAbility = specialAbility;

    // declaring a method on the object
    this.getDetails = function() {
      return `${this._name} can ${this._specialAbility}`;
    };
  }
}

// creating new instances of Hero
const IronMan = new Hero('Iron Man', 'fly');

console.log(IronMan.getDetails()); // Iron Man can fly
```
{% endcode %}

## Factory pattern

Another **class-based creational pattern**.

A **generic interface that delegates the responsibility of object instantiation to its subclasses**.

Used **when we need to manage or manipulate collections of objects that are different yet have many similar characteristics**.

**Example**, create a factory class named `BallFactory` that has a method and depending on the parameters it delegates the object instantiation responsibility to the respective class. If the type parameter is `"football"` or `"soccer"` object instantiation is handled by `Football` class but if it is `"basketball"` object instantiation is handled by `Basketball` class.

{% code title="Factory.js" %}
```javascript
class BallFactory {
  constructor() {
    this.createBall = function(type) {
      let ball;
      if (type === 'football' || type === 'soccer') ball = new Football();
      else if (type === 'basketball') ball = new Basketball();
      ball.roll = function() {
        return `The ${this._type} is rolling.`;
      };

      return ball;
    };
  }
}

class Football {
  constructor() {
    this._type = 'football';
    this.kick = function() {
      return 'You kicked the football.';
    };
  }
}

class Basketball {
  constructor() {
    this._type = 'basketball';
    this.bounce = function() {
      return 'You bounced the basketball.';
    };
  }
}

// creating objects
const factory = new BallFactory();

const myFootball = factory.createBall('football');
const myBasketball = factory.createBall('basketball');

console.log(myFootball.roll()); // The football is rolling.
console.log(myBasketball.roll()); // The basketball is rolling.
console.log(myFootball.kick()); // You kicked the football.
console.log(myBasketball.bounce()); // You bounced the basketball.

```
{% endcode %}

## Prototype pattern

**Object-based creational design pattern**.

We use a sort of a **“skeleton” of an existing object to create or instantiate new objects**.

It **utilizes prototypal inheritance instead of a classic object-oriented inheritance**. Hence, it plays to JS's strength and has native support.

**Example,** we have a `car` object that we use as the prototype to create another object `myCar` with JS’s `Object.create` feature and define an extra property `owner` on the new object.

{% code title="Prototype.js" %}
```javascript
// using Object.create as was recommended by ES5 standard
const car = {
  noOfWheels: 4,
  start() {
    return 'started';
  },
  stop() {
    return 'stopped';
  },
};

// Object.create(proto[, propertiesObject])

const myCar = Object.create(car, { owner: { value: 'John' } });

console.log(myCar.__proto__ === car); // true

```
{% endcode %}

## Singleton Pattern

**Special creational design pattern.**

**Only one instance of a class can exist.**

**If no instance of the singleton class exists then a new instance is created and returned but if an instance already exists then the reference to the existing instance is returned.**

**Example**, we have a `Database` class that is a Singleton. First, we create an object `mongo` by using the `new` operator to invoke the `Database` class constructor. This time an object is instantiated because none already exists. The second time, when we create the `mysql` object, no new object is instantiated but instead the reference to the object that was instantiated earlier i.e. the `mongo` object is returned.\


{% code title="Singleton.js" %}
```javascript
class Database {
  constructor(data) {
    if (Database.exists) {
      return Database.instance;
    }
    this._data = data;
    Database.instance = this;
    Database.exists = true;
    return this;
  }

  getData() {
    return this._data;
  }

  setData(data) {
    this._data = data;
  }
}

// usage
const mongo = new Database('mongo');
console.log(mongo.getData()); // mongo

const mysql = new Database('mysql');
console.log(mysql.getData()); // mongo

```
{% endcode %}

## Adapter Pattern

**Structural pattern.**&#x20;

**The interface of one class is translated into another.** Lets classes work together that could not otherwise because of incompatible interfaces.

Used to create **wrappers for new refactored APIs so that other existing old APIs can still work with them**.

**Example**, we have an old API i.e. `OldCalculator` class and a new API i.e. `NewCalculator` class. The `OldCalculator` class provides an `operation`method for both addition and subtraction while the `NewCalculator`provides separate methods for addition and subtraction. The Adapter class `CalcAdapter`wraps the `NewCalculator` to add the `operation` method to the public facing API while using its own addition and subtraction implementation under the hood.

{% code title="Adapter.js" %}
```javascript
// old interface
class OldCalculator {
  constructor() {
    this.operations = function(term1, term2, operation) {
      switch (operation) {
        case 'add':
          return term1 + term2;
        case 'sub':
          return term1 - term2;
        default:
          return NaN;
      }
    };
  }
}

// new interface
class NewCalculator {
  constructor() {
    this.add = function(term1, term2) {
      return term1 + term2;
    };
    this.sub = function(term1, term2) {
      return term1 - term2;
    };
  }
}

// Adapter Class
class CalcAdapter {
  constructor() {
    const newCalc = new NewCalculator();

    this.operations = function(term1, term2, operation) {
      switch (operation) {
        case 'add':
          // using the new implementation under the hood
          return newCalc.add(term1, term2);
        case 'sub':
          return newCalc.sub(term1, term2);
        default:
          return NaN;
      }
    };
  }
}

// usage
const oldCalc = new OldCalculator();
console.log(oldCalc.operations(10, 5, 'add')); // 15

const newCalc = new NewCalculator();
console.log(newCalc.add(10, 5)); // 15

const adaptedCalc = new CalcAdapter();
console.log(adaptedCalc.operations(10, 5, 'add')); // 15;
```
{% endcode %}

## Composite pattern

**Structural design pattern.**

**Composes objects into tree-like structures to represent whole-part hierarchies**. Each **node** in the tree-like structure can be either an **individual object or a composed collection of objects**. **Regardless, each node is treated uniformly**.

A **Multi-level Menu Structure**:

![](https://cdn-images-1.medium.com/max/1600/1*yAkeYCKDaRQtMRAV2Kx5sA.png)

**Example: a multi-level menu**. Each node can be a distinct option or it can be a menu itself which has multiple options as its child. A node component with children is a **composite** component while a node component without any child is a **leaf component**.

In this example, we create a **base class of `Component` that implements the common functionalities** needed and abstracts the other methods needed. The base class also has a **static method that utilizes recursion to traverse a composite tree structure** made with its subclasses. Then we create **two subclasses extending the base class — `Leaf` that does not have any children and `Composite`** that can have children and hence have methods handling adding, searching and removing child functionalities. The two subclasses are used to create a composite structure i.e. a tree in this case.

{% code title="Composite.js" %}
```javascript
class Component {
  constructor(name) {
    this._name = name;
  }

  getNodeName() {
    return this._name;
  }

  // abstract methods that need to be overridden
  getType() {}

  addChild(component) {}

  removeChildByName(componentName) {}

  removeChildByIndex(index) {}

  getChildByName(componentName) {}

  getChildByIndex(index) {}

  noOfChildren() {}

  static logTreeStructure(root) {
    let treeStructure = '';
    function traverse(node, indent = 0) {
      treeStructure += `${'--'.repeat(indent)}${node.getNodeName()}\n`;
      indent++;
      for (let i = 0, length = node.noOfChildren(); i < length; i++) {
        traverse(node.getChildByIndex(i), indent);
      }
    }

    traverse(root);
    return treeStructure;
  }
}

class Leaf extends Component {
  constructor(name) {
    super(name);
    this._type = 'Leaf Node';
  }

  getType() {
    return this._type;
  }

  noOfChildren() {
    return 0;
  }
}

class Composite extends Component {
  constructor(name) {
    super(name);
    this._type = 'Composite Node';
    this._children = [];
  }

  getType() {
    return this._type;
  }

  addChild(component) {
    this._children = [...this._children, component];
  }

  removeChildByName(componentName) {
    this._children = [...this._children].filter(component => component.getNodeName() !== componentName);
  }

  removeChildByIndex(index) {
    this._children = [...this._children.slice(0, index), ...this._children.slice(index + 1)];
  }

  getChildByName(componentName) {
    return this._children.find(component => component.name === componentName);
  }

  getChildByIndex(index) {
    return this._children[index];
  }

  noOfChildren() {
    return this._children.length;
  }
}

// usage
const tree = new Composite('root');
tree.addChild(new Leaf('left'));
const right = new Composite('right');
tree.addChild(right);
right.addChild(new Leaf('right-left'));
const rightMid = new Composite('right-middle');
right.addChild(rightMid);
right.addChild(new Leaf('right-right'));
rightMid.addChild(new Leaf('left-end'));
rightMid.addChild(new Leaf('right-end'));

// log
console.log(Component.logTreeStructure(tree));
/*
root
--left
--right
----right-left
----right-middle
------left-end
------right-end
----right-right
*/
```
{% endcode %}

## Decorator Pattern

**Structural design pattern.**

**Adds behavior or functionalities to existing classes dynamically**. It is a viable **alternative to sub-classing**.

Easy to implement because **JS allows us to add methods and properties to object dynamically**. The simplest approach would be to just add a property to an object but it will not be efficiently reusable.

**Example**, create a `Book` class. Further create two decorator functions that accept a book object and returns a "decorated" `book` object — `giftWrap` that adds one new attribute and one new function and `hardbindBook` that adds one new attribute and edits the value of one existing attribute.

```javascript
class Book {
  constructor(title, author, price) {
    this._title = title;
    this._author = author;
    this.price = price;
  }

  getDetails() {
    return `${this._title} by ${this._author}`;
  }
}

// decorator 1
function giftWrap(book) {
  book.isGiftWrapped = true;
  book.unwrap = function() {
    return `Unwrapped ${book.getDetails()}`;
  };

  return book;
}

// decorator 2
function hardbindBook(book) {
  book.isHardbound = true;
  book.price += 5;
  return book;
}

// usage
const alchemist = giftWrap(new Book('The Alchemist', 'Paulo Coelho', 10));

console.log(alchemist.isGiftWrapped); // true
console.log(alchemist.unwrap()); // 'Unwrapped The Alchemist by Paulo Coelho'

const inferno = hardbindBook(new Book('Inferno', 'Dan Brown', 15));

console.log(inferno.isHardbound); // true
console.log(inferno.price); // 20
```

## Facade pattern

**Structural design pattern.**

**Provides a unified and simpler public facing interface for ease of use that shields away from the complexities** of its consisting subsystems or subclasses.

**Example**, create a public facing API with the class `ComplaintRegistry`. It exposes only one method to be used by the client i.e. `registerComplaint`. It internally handles instantiating required objects of either `ProductComplaint` or `ServiceComplaint` based on the type argument. It also handles all the other complex functionalities like generating a unique ID, storing the complaint in memory, etc. But, all these complexities are hidden away using the Facade pattern.

{% code title="Facade.js" %}
```javascript
let currentId = 0;

class ComplaintRegistry {
  registerComplaint(customer, type, details) {
    const id = ComplaintRegistry._uniqueIdGenerator();
    let registry;
    if (type === 'service') {
      registry = new ServiceComplaints();
    } else {
      registry = new ProductComplaints();
    }
    return registry.addComplaint({ id, customer, details });
  }

  static _uniqueIdGenerator() {
    return ++currentId;
  }
}

class Complaints {
  constructor() {
    this.complaints = [];
  }

  addComplaint(complaint) {
    this.complaints.push(complaint);
    return this.replyMessage(complaint);
  }

  getComplaint(id) {
    return this.complaints.find(complaint => complaint.id === id);
  }

  replyMessage(complaint) {}
}

class ProductComplaints extends Complaints {
  constructor() {
    super();
    if (ProductComplaints.exists) {
      return ProductComplaints.instance;
    }
    ProductComplaints.instance = this;
    ProductComplaints.exists = true;
    return this;
  }

  replyMessage({ id, customer, details }) {
    return `Complaint No. ${id} reported by ${customer} regarding ${details} have been filed with the Products Complaint Department. Replacement/Repairment of the product as per terms and conditions will be carried out soon.`;
  }
}

class ServiceComplaints extends Complaints {
  constructor() {
    super();
    if (ServiceComplaints.exists) {
      return ServiceComplaints.instance;
    }
    ServiceComplaints.instance = this;
    ServiceComplaints.exists = true;
    return this;
  }

  replyMessage({ id, customer, details }) {
    return `Complaint No. ${id} reported by ${customer} regarding ${details} have been filed with the Service Complaint Department. The issue will be resolved or the purchase will be refunded as per terms and conditions.`;
  }
}

// usage
const registry = new ComplaintRegistry();

const reportService = registry.registerComplaint('Martha', 'service', 'availability');
// 'Complaint No. 1 reported by Martha regarding availability have been filed with the Service Complaint Department. The issue will be resolved or the purchase will be refunded as per terms and conditions.'

const reportProduct = registry.registerComplaint('Jane', 'product', 'faded color');
// 'Complaint No. 2 reported by Jane regarding faded color have been filed with the Products Complaint Department. Replacement/Repairment of the product as per terms and conditions will be carried out soon.'
```
{% endcode %}

## Flyweight Pattern

**Structural design pattern.**&#x20;

Efficient data sharing through fine-grained objects. It is used for **efficiency and memory conservation purposes**.

Used for **caching** purposes. In fact, modern browsers use a variant of flyweight pattern to prevent loading same images twice.

**Example**, create a fine-grained flyweight class `Icecream` for sharing data regarding ice-cream flavors and a factory class `IcecreamFactory` to create those flyweight objects. For memory conservation, the objects are recycled if the same object is instantiated twice. This is a simple example of flyweight implementation.

{% code title="Flyweight.js" %}
```javascript
// flyweight class
class Icecream {
  constructor(flavour, price) {
    this.flavour = flavour;
    this.price = price;
  }
}

// factory for flyweight objects
class IcecreamFactory {
  constructor() {
    this._icecreams = [];
  }

  createIcecream(flavour, price) {
    let icecream = this.getIcecream(flavour);
    if (icecream) {
      return icecream;
    } else {
      const newIcecream = new Icecream(flavour, price);
      this._icecreams.push(newIcecream);
      return newIcecream;
    }
  }

  getIcecream(flavour) {
    return this._icecreams.find(icecream => icecream.flavour === flavour);
  }
}

// usage
const factory = new IcecreamFactory();

const chocoVanilla = factory.createIcecream('chocolate and vanilla', 15);
const vanillaChoco = factory.createIcecream('chocolate and vanilla', 15);

// reference to the same object
console.log(chocoVanilla === vanillaChoco); // true

```
{% endcode %}

## Proxy Pattern

**Structural design pattern.**

**Acts as a surrogate or placeholder for another object to control access to it.**

Used in situations **where a target object is under constraints and may not be able to handle all its responsibility efficiently**. A proxy, in this case, usually provides the same interface to the client and **adds a level of indirection to support controlled access to the target object to avoid undue pressure on it**.

Useful when working with **network request heavy applications to avoid unnecessary or redundant network requests**.

**Example**, we will use two new ES6 features [**Proxy**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) and [**Reflect**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect).

* A **Proxy object is used to define custom behavior for fundamental operations of a JS object** (remember, function and arrays are also object in JS). It is a constructor method that can be used to create a `Proxy`object. It accepts a `target` object that is to be proxied and a `handler` object that will define the necessary customization. The handler object allows defining some trap functions like `get`, `set`, `has`, `apply`, etc. that are used to add custom behavior attached to their usage.
* **`Reflect`,** on the other hand, is a built-in object that **provides similar methods that are supported by the handler object of Proxy as static methods on itself. It is not a constructor, it's static methods are used for intercept-able JS operations.**

Now, we create a function that can be thought of as a network request. We named it as `networkFetch`. It accepts a URL and responds accordingly. We want to implement a proxy where we only get the response from the network if it is not available in our cache otherwise we just return a response from the cache. The `cache` global variable will store our cached responses. We create a proxy named `proxiedNetworkFetch` with our original `networkFetch` as the `target`and use apply method in our `handler` object to proxy the function invocation. The apply method gets passed on the `target` object itself, this value as `thisArg` and the arguments passed to it in an array-like structure `args`. We check if the passed url argument is in the cache, if it exists in the cache we return the response from there, never invoking the original target function. If it does not, then we use the `Reflect.apply` method to invoke the `target`function with `thisArg` (although it's not of any significance in our case here) and the arguments it was passed.

{% code title="Proxy.js" %}
```javascript
// Target
function networkFetch(url) {
  return `${url} - Response from network`;
}

// Proxy
// ES6 Proxy API = new Proxy(target, handler);
const cache = [];
const proxiedNetworkFetch = new Proxy(networkFetch, {
  apply(target, thisArg, args) {
    const urlParam = args[0];
    if (cache.includes(urlParam)) {
      return `${urlParam} - Response from cache`;
    } else {
      cache.push(urlParam);
      return Reflect.apply(target, thisArg, args);
    }
  },
});

// usage
console.log(proxiedNetworkFetch('dogPic.jpg')); // 'dogPic.jpg - Response from network'
console.log(proxiedNetworkFetch('dogPic.jpg')); // 'dogPic.jpg - Response from cache'

```
{% endcode %}

## Chain of Responsibility Pattern

**Behavioral design pattern.**

**Provides a chain of loosely coupled objects. Each of these objects can choose to act on or handle the request of the client.**

Example: the **event bubbling in DOM** in which an event propagates through a series of nested DOM elements, one of which may have an “event listener” attached to listen and act on the event.

**Example**, create a class `CumulativeSum` which can be instantiated with an optional `initialValue`. It has a method `add` that adds the passed value to the `sum` attribute of the object and returns the `object` itself to allow chaining of `add` method calls.

{% code title="ChainOfResponsibility.js" %}
```javascript
class CumulativeSum {
  constructor(intialValue = 0) {
    this.sum = intialValue;
  }

  add(value) {
    this.sum += value;
    return this;
  }
}

// usage
const sum1 = new CumulativeSum();
console.log(sum1.add(10).add(2).add(50).sum); // 62


const sum2 = new CumulativeSum(10);
console.log(sum2.add(10).add(20).add(5).sum); // 45

```
{% endcode %}

## Command Pattern

**Behavioral design pattern.**

**Encapsulates actions or operations as objects**.

Allows **loose coupling** of systems and classes **by separating the objects that request an operation or invoke a method from the ones that execute or process the actual implementation**.

The clipboard interaction API resembles the command pattern somewhat. If you are a [**Redux**](https://redux.js.org/) user, you have already come across the Command pattern. The actions, that allow the awesome time-travel debugging feature, are nothing but encapsulated operations that can be tracked to redo or undo operations. Hence, time-travelling made possible.

**Example**, we have a class `SpecialMath` that has multiple methods and a `Command` class that encapsulates commands that are to be executed on its subject i.e. an object of the `SpecialMath` class. The `Command` class also keeps track of all the commands executed which can be used to extend its functionality to include undo and redo type operations.

{% code title="Command.js" %}
```javascript
class SpecialMath {
  constructor(num) {
    this._num = num;
  }

  square() {
    return this._num ** 2;
  }

  cube() {
    return this._num ** 3;
  }

  squareRoot() {
    return Math.sqrt(this._num);
  }
}

class Command {
  constructor(subject) {
    this._subject = subject;
    this.commandsExecuted = [];
  }
  execute(command) {
    this.commandsExecuted.push(command);
    return this._subject[command]();
  }
}

// usage
const x = new Command(new SpecialMath(5));
x.execute('square');
x.execute('cube');

console.log(x.commandsExecuted); // ['square', 'cube']

```
{% endcode %}

## Iterator Pattern

**Behavioral design pattern.**

A way to **access the elements of an aggregate object sequentially without exposing its underlying representation**.

**We step through an ordered set of values one at a time by calling `next()` until we reach the end**. The introduction of **Iterator and Generators in ES6 made the implementation of iterator pattern extremely straightforward**.

Two examples below, first one `IteratorClass` uses Iterator spec while the other one `iteratorUsingGenerator` uses Generator functions.

The `Symbol.iterator` ( `Symbol` - a new kind of primitive data type) is used to specify the default iterator for an object. It is must be defined for a collection to be able to use `for...of` looping construct. In the first example, we define the constructor to store some collection of data and then define `Symbol.iterator`which returns an object with `next` method for iteration.

For the second case, we define a generator function passing it an array of data and return its elements iteratively using `next` and `yield`. A generator function is a special type of function that works as a factory for iterators and can explicitly maintain its own internal state and yield values iteratively. It can pause and resume its own execution cycle.

{% code title="Iterator.js" %}
```javascript
// using Iterator
class IteratorClass {
  constructor(data) {
    this.index = 0;
    this.data = data;
  }

  [Symbol.iterator]() {
    return {
      next: () => {
        if (this.index < this.data.length) {
          return { value: this.data[this.index++], done: false };
        } else {
          this.index = 0; // to reset iteration status
          return { done: true };
        }
      },
    };
  }
}

// using Generator
function* iteratorUsingGenerator(collection) {
  var nextIndex = 0;

  while (nextIndex < collection.length) {
    yield collection[nextIndex++];
  }
}

// usage
const gen = iteratorUsingGenerator(['Hi', 'Hello', 'Bye']);

console.log(gen.next().value); // 'Hi'
console.log(gen.next().value); // 'Hello'
console.log(gen.next().value); // 'Bye'
```
{% endcode %}

## Mediator Pattern

**Behavioral design pattern**.

**Encapsulates how a set of objects interact with each other**. Provides the **central authority over a group of objects** by promoting loose coupling by keeping objects from referring to each other explicitly.

**Example**, we have `TrafficTower` as Mediator that controls the way `Airplane` objects interact with each other. All the `Airplane` objects register themselves with a `TrafficTower` object and it is the mediator class object that handles how an `Airplane` object receives coordinates data of all the other `Airplane` objects.

{% code title="Mediator.js" %}
```javascript
class TrafficTower {
  constructor() {
    this._airplanes = [];
  }

  register(airplane) {
    this._airplanes.push(airplane);
    airplane.register(this);
  }

  requestCoordinates(airplane) {
    return this._airplanes.filter(plane => airplane !== plane).map(plane => plane.coordinates);
  }
}

class Airplane {
  constructor(coordinates) {
    this.coordinates = coordinates;
    this.trafficTower = null;
  }

  register(trafficTower) {
    this.trafficTower = trafficTower;
  }

  requestCoordinates() {
    if (this.trafficTower) return this.trafficTower.requestCoordinates(this);
    return null;
  }
}

// usage
const tower = new TrafficTower();

const airplanes = [new Airplane(10), new Airplane(20), new Airplane(30)];
airplanes.forEach(airplane => {
  tower.register(airplane);
});

console.log(airplanes.map(airplane => airplane.requestCoordinates())) 
// [[20, 30], [10, 30], [10, 20]]

```
{% endcode %}

## Observer Pattern

**Behavioral design pattern.**

**Defines one-to-many dependencies between objects so that when one object (publisher) changes its state, all the other dependent objects (subscribers) are notified and updated automatically**. Aka **PubSub** (Publisher/Subscribers) or **Event Dispatcher/Listeners** Pattern.&#x20;

**Example**, create a simple `Subject` class that has methods to add and remove objects of `Observer` class from subscriber collection. Also, a `fire`method to propagate any changes in the `Subject` class object to the subscribed Observers. The `Observer` class, on the other hand, has its internal state and a method to update its internal state based on the change propagated from the `Subject` it has subscribed to.

{% code title="Observer.js" %}
```javascript
class Subject {
  constructor() {
    this._observers = [];
  }

  subscribe(observer) {
    this._observers.push(observer);
  }

  unsubscribe(observer) {
    this._observers = this._observers.filter(obs => observer !== obs);
  }

  fire(change) {
    this._observers.forEach(observer => {
      observer.update(change);
    });
  }
}

class Observer {
  constructor(state) {
    this.state = state;
    this.initialState = state;
  }

  update(change) {
    let state = this.state;
    switch (change) {
      case 'INC':
        this.state = ++state;
        break;
      case 'DEC':
        this.state = --state;
        break;
      default:
        this.state = this.initialState;
    }
  }
}

// usage
const sub = new Subject();

const obs1 = new Observer(1);
const obs2 = new Observer(19);

sub.subscribe(obs1);
sub.subscribe(obs2);

sub.fire('INC');

console.log(obs1.state); // 2
console.log(obs2.state); // 20

```
{% endcode %}

## State Pattern

**Behavioral design pattern.**

**Allows an object to alter its behavior based on changes to its internal state**. The object returned by a State pattern class seems to change its class. It **provides state-specific logic to a limited set of objects in which each object type represents a particular state**.

**Example** of a traffic light to understand this pattern. The `TrafficLight` class changes the object it returns based on its internal state which is an object of `Red`, `Yellow` or `Green` class.

{% code title="State.js" %}
```javascript
class TrafficLight {
  constructor() {
    this.states = [new GreenLight(), new RedLight(), new YellowLight()];
    this.current = this.states[0];
  }

  change() {
    const totalStates = this.states.length;
    let currentIndex = this.states.findIndex(light => light === this.current);
    if (currentIndex + 1 < totalStates) this.current = this.states[currentIndex + 1];
    else this.current = this.states[0];
  }

  sign() {
    return this.current.sign();
  }
}

class Light {
  constructor(light) {
    this.light = light;
  }
}

class RedLight extends Light {
  constructor() {
    super('red');
  }

  sign() {
    return 'STOP';
  }
}

class YellowLight extends Light {
  constructor() {
    super('yellow');
  }

  sign() {
    return 'STEADY';
  }
}

class GreenLight extends Light {
	constructor() {
		super('green');
	}

	sign() {
		return 'GO';
	}
}

// usage
const trafficLight = new TrafficLight();

console.log(trafficLight.sign()); // 'GO'
trafficLight.change();

console.log(trafficLight.sign()); // 'STOP'
trafficLight.change();

console.log(trafficLight.sign()); // 'STEADY'
trafficLight.change();

console.log(trafficLight.sign()); // 'GO'
trafficLight.change();

console.log(trafficLight.sign()); // 'STOP'
```
{% endcode %}

## Strategy Pattern

**Behavioral design pattern.**

Allows **encapsulation of alternative algorithms for a particular task**. It defines a **family of algorithms and encapsulates them in such a way that they are interchangeable at runtime** without client interference or knowledge.

**Example**, create a class `Commute` for encapsulating all the possible strategies for commuting to work. Then, we define three strategies namely `Bus`, `PersonalCar` and `Taxi`. Using this pattern we can swap the implementation to use for the `travel` method of the `Commute` object at runtime.

{% code title="Strategy.js" %}
```javascript
// encapsulation
class Commute {
  travel(transport) {
    return transport.travelTime();
  }
}

class Vehicle {
  travelTime() {
    return this._timeTaken;
  }
}

// strategy 1
class Bus extends Vehicle {
  constructor() {
    super();
    this._timeTaken = 10;
  }
}

// strategy 2
class Taxi extends Vehicle {
  constructor() {
    super();
    this._timeTaken = 5;
  }
}

// strategy 3
class PersonalCar extends Vehicle {
  constructor() {
    super();
    this._timeTaken = 3;
  }
}

// usage
const commute = new Commute();

console.log(commute.travel(new Taxi())); // 5
console.log(commute.travel(new Bus())); // 10

```
{% endcode %}

## Template Pattern

**Behavioral design pattern.**

**Defining the skeleton of the algorithm or implementation of an operation, but deferring some steps to subclasses**. It lets subclasses redefine certain steps of an algorithm without changing the algorithm’s outward structure.

**Example**, we have a Template class `Employee` that implements `work`method partially. It is for the subclasses to implement responsibilities method to make it work as a whole. We then create two subclasses `Developer`and `Tester` that extend the Template class and implement the required method to fill the implementation gap.

{% code title="Template.js" %}
```javascript
class Employee {
  constructor(name, salary) {
    this._name = name;
    this._salary = salary;
  }

  work() {
    return `${this._name} handles ${this.responsibilities() /* gap to be filled by subclass */}`;
  }

  getPaid() {
    return `${this._name} got paid ${this._salary}`;
  }
}

class Developer extends Employee {
  constructor(name, salary) {
    super(name, salary);
  }

  // details handled by subclass
  responsibilities() {
    return 'application development';
  }
}

class Tester extends Employee {
  constructor(name, salary) {
    super(name, salary);
  }

  // details handled by subclass
  responsibilities() {
    return 'testing';
  }
}

// usage
const dev = new Developer('Nathan', 100000);
console.log(dev.getPaid()); // 'Nathan got paid 100000'
console.log(dev.work()); // 'Nathan handles application development'

const tester = new Tester('Brian', 90000);
console.log(tester.getPaid()); // 'Brian got paid 90000'
console.log(tester.work()); // 'Brian handles testing'

```
{% endcode %}

## Further reading (books)

1. [Design Patterns: Elements Of Reusable Object-Oriented Software](https://en.wikipedia.org/wiki/Design_Patterns) by _Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides (Gang of Four)_
2. [Learn JavaScript Design Patterns ](https://addyosmani.com/resources/essentialjsdesignpatterns/book/)by _Addy Osmani_
3. [JavaScript Patterns](http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752) by _Stoyan Stefanov_
