Creational Patterns in ES6+ using Game of Thrones
A Design Pattern describes an established solution to the most commonly encountered problems in software design. Let's dig deep into creational patterns in ES6+ using Game of Thrones!

In software engineering, a Design Pattern describes an established solution to the most commonly encountered problems in software design. It represents the best practices evolved over a long period -through trial and error- by experienced software developers.

In this article we will talk about the Creational Design Patterns. Creational Patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation.

The most common Creational Patterns are:

  • Factory Method
  • Abstract Factory
  • Builder
  • Prototype
  • Singleton

#Factory Method Pattern

The factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. Wait, What does this mean?

Let’s pretend that we want to be able to create soldiers. These soldiers can be from the Targaryen’s house or from the Lannister’s house.

According to the "Factory Method" pattern, we will need:

  • An interface class to define our soldiers
  • A class for each type of soldier to extend the abilities of each house
  • A class to request the creation of a new soldier regardless of which house he comes from
class Soldier {
  constructor(name) {
    this.name = name;
    this.attack = this.attack.bind(this);
  }

  attack() {}
}

class LannisterSoldier extends Soldier {
  attack() {
    return "A Lannister always pays his debts";
  }
}

class TargaryenSoldier extends Soldier {
  attack() {
    return "Fire and blond";
  }
}

class Spawn {
  constructor(type, name) {
    if (type === "lannister") return new LannisterSoldier(name);
    else return new TargaryenSoldier(name);
  }
}

(() => {
  const lannister = new Spawn("lannister", "soldierA");
  const targaryen = new Spawn("targaryen", "soldierB");
  console.log(lannister.attack());
  console.log(targaryen.attack());
})();

#When to use the Factory Method Pattern?

  • When the implementation of an interface or an abstract class is expected to change frequently
  • When the current implementation cannot comfortably accommodate new change
  • When the initialization process is relatively simple, and the constructor only requires a handful of parameters

#Abstract Factory Pattern

Disclaim: The Abstract Factory Pattern is strongly based on objects. Applying this pattern to a functional language (no javascript is not a pure object-oriented language, please do not start with flame) is not so trivial, this is why javascript implementation is different.

The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes. In a normal usage, the client software creates a concrete implementation of the abstract factory and then uses the generic interface of the factory to create the concrete objects that are part of the theme. The client doesn’t know (or care) which concrete objects it gets from each of these internal factories since it uses only the generic interfaces of their products.

Let’s pretend that for our game we want to manage the houses individually, each house must be able to manage an heir to the throne and his subjects.

According to the "Factory Method" pattern, we will need:

  • An interface class to define our heir to the throne
  • A class for each heir to the throne
  • An interface class to define our subject
  • A class for each subjects
  • An interface class to define our houses
  • A class for each houses that will return an instance of her HeirToTheThroneand Subject
// Define Heir To The Throne

class HeirToTheThrone {
  constructor(name, isActualOnTheThrone) {
    this.name = name;
    this.isActualOnTheThrone = isActualOnTheThrone;
    this.getTheThrone = this.getTheThrone.bind(this);
  }
  getTheThrone() {}
}

class HeirToTheThroneLannister extends HeirToTheThrone {
  getTheThrone() {
    console.log("Kill all");
  }
}

class HeirToTheThroneTargaryen extends HeirToTheThrone {
  getTheThrone() {
    console.log("Burn all");
  }
}

// Define Subject

class Subject {
  constructor(name) {
    this.name = name;
    this.speak = this.speak.bind(this);
  }
  speak() {}
}

class SubjectLannister extends Subject {
  speak() {
    console.log("I love Cersei");
  }
}

class SubjectTargaryen extends Subject {
  speak() {
    console.log("I love Daenerys");
  }
}

// Define Houses
class House {
  constructor() {
    this.getHeir = this.getHeir.bind(this);
    this.getSubject = this.getSubject.bind(this);
  }
  getHeir() {}
  getSubject() {}
}

class Lannister extends House {
  getHeir() {
    return new HeirToTheThroneLannister("Cersei", true);
  }
  getSubject(name) {
    return new SubjectLannister(name);
  }
}

class Targaryen extends House {
  getHeir() {
    return new HeirToTheThroneTargaryen("Daenerys", true);
  }
  getSubject(name) {
    return new SubjectTargaryen(name);
  }
}

(() => {
  const lannister = new Lannister();
  const targaryen = new Targaryen();
  lannister.getHeir().getTheThrone();
  lannister.getSubject().speak();
  targaryen.getHeir().getTheThrone();
  targaryen.getSubject().speak();
})();

#When to use the Builder Design Pattern?

  • The client is independent on how we create and compose the objects in the system
  • The system consists of multiple families of objects, and these families are designed to be used together
  • We need a run-time value to construct a particular dependency

#Builder Pattern

The intent of the Builder design pattern is to separate the construction of a complex object from its representation. When the complexity of creating an object increases, the Builder pattern can separate out the instantiation process by using another object (a builder) to construct the object.

Let’s pretend that for our game we want to create a navy for each house. Each family will have a certain number of ships and warriors available. To facilitate the creation we want to be able to invoke only the makeNavy method that will automatically create everything you need through a configuration.

According to the "Builder" pattern, we will need:

  • A class to start the creation of the Navy
  • A Builder interface class to define our builder
  • A ConcreteBuilder class that will be responsible for creating all the objects in our army
  • The Soldier and Ship class that will will be responsible for creating the specific soldiers or ships
class Lannister {
  constructor() {
    this.soldiers = [];
    this.ships = [];
    this.makeNavy = this.makeNavy.bind(this);
  }
  makeNavy(soldiers, ships) {
    const Build = new ConcreteBuilder();
    for (let i = 0; i < soldiers; i++) {
      this.soldiers.push(Build.createSoldier());
    }
    for (let i = 0; i < ships; i++) {
      this.ships.push(Build.createShip());
    }
  }
}

class Builder {
  createSoldier() {}
  createShip() {}
}

class ConcreteBuilder extends Builder {
  createSoldier() {
    const soldier = new Soldier();
    return soldier;
  }

  createShip() {
    const ship = new Ship();
    return ship;
  }
}

class Soldier {
  constructor() {
    console.log("Created Soldier");
  }
}

class Ship {
  constructor() {
    console.log("Created Ship");
  }
}

(() => {
  const lannister = new Lannister();
  lannister.makeNavy(100, 10);
})();

#When to use the Builder Design Pattern?

  • When the process involved in creating an object is extremely complex, with lots of mandatory and optional parameters
  • When an increase in the number of constructor parameters leads to a large list of constructors
  • When the client expects different representations for the object that’s constructed

#Prototype Pattern

The Prototype Pattern allows you to specify the kinds of objects to create using a prototypical instance, and create new objects from the ‘skeleton’ of an existing object, thus boosting performance and keeping memory footprints to a minimum.

Let’s pretend that for our game we want to create a white walkers’ army we don’t have great pretensions for this army, we need only that they be really many, that they all have the same characteristics and that they don’t occupy us too much memory in our application.

According to the "Prototype" pattern, we will need:

  • A class to store the information about the White Walker
  • A clone method that returns another instance clone of the instance
class WhiteWalker {
  constructor(force, weight) {
    this.force = force;
    this.weight = weight;
  }

  clone() {
    console.log("cloned");
    return new WhiteWalker(this.name, this.weight);
  }
}

(() => {
  const firstWalker = new WhiteWalker();
  const walkers = [firstWalker];
  for (let i = 0; i < 100; i++) {
    walkers.push(firstWalker.clone());
  }
})();

#The Pros and Cons of the Prototype Pattern

PROS

  • The Prototype Pattern helps reduce costs, time and contributes to increasing the performance of the program by not using the new operator to create new objects.
  • It helps reduce complexity for object initialization: because each class only implements its own way of cloning.
  • We can also avoid classifying and creating multiple sub-classes to initialize objects such as the Abstract Factory Pattern.
  • It helps you increase the flexibility of the system because it allows creating new objects by changing some properties of the original object that it copied.

CONS

  • Cloning complex objects that have circular references might be very tricky

#Singleton Pattern

The Singleton Design Pattern aims to keep a check on initialization of objects of a particular class by** ensuring that only one instance of the object exists throughout the Program.** This is useful when exactly one object is needed to coordinate actions across the system.

Let’s pretend that for our game we want to be sure that nobody can be the Mother of Dragons except the first one who will become it.

According to the "Singleton Method" pattern, we will need:

  • A class to store the information of the Mother of Dragons
  • An instance of the Mother of Dragon saved
let INSTANCE = null;

class MotherOfDragons {
  constructor(name, dragons) {
    if (!!INSTANCE) return INSTANCE;
    this.dragons = dragons;
    this.name = name;
    this.getMyDragons = this.getMyDragons.bind(this);
    INSTANCE = this;
  }

  getMyDragons() {
    console.log(`I'm ${this.name} and my dragons are`, this.dragons);
  }
}

(() => {
  const dragonsMother = new MotherOfDragons("Daenerys Targaryen", [
    "Drogon",
    "Rhaegal",
    "Viserion"
  ]);
  const dragonsMother2 = new MotherOfDragons("Cercei Targaryen", [
    "Tirion",
    "Jennifer",
    "Goblin"
  ]);
  dragonsMother.getMyDragons();
  dragonsMother2.getMyDragons();
  console.log(dragonsMother instanceof MotherOfDragons);
  console.log(dragonsMother2 instanceof MotherOfDragons);
  console.log(dragonsMother2 === dragonsMother);
})();

#When to use the Singleton Design Pattern?

  • For resources that are expensive to create (like database connection objects)
  • It’s good practice to keep all loggers as Singletons which increases performance
  • Classes which provide access to configuration settings for the application
  • Classes that contain resources that are accessed in shared mode