DEV Community

Cover image for Design Patterns in JavaScript: Creational Patterns
Furkan Gulsen
Furkan Gulsen

Posted on

Design Patterns in JavaScript: Creational Patterns

In daily life, programmers may encounter many errors while writing code, and naturally they develop methods to solve these problems. The solutions developed by different printers in different projects are very similar to each other. This is where Design Patterns come into play.

Design patterns are solutions to common problems software developers face during software development.

Let's examine the Design Patterns in items for a better understanding:

  • It is generally based on OOP. But it can be used regardless of language and technology.
  • They are proven solution methods used by software developers.
  • They are the general solution plans applied to the problem.

We collect Design Patterns under 3 headings:

  • Creative Patterns
  • Structural Patterns
  • Behavioral Patterns

In this article, I will talk about Creative Patterns:

Creational Patterns

It is a pattern used in the creation and management of objects. They provide object creation mechanisms that increase code flexibility and reusability.

Image description

Factory Method

It defines an interface to create a single object and allows subclasses to decide which class to instantiate.

Example: Let's define a class named Person.

class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
}
Enter fullscreen mode Exit fullscreen mode

Now let's add our Factory method:

class PersonFactory {
    static add(name, age) {
        return new Person(name, age);
    }
}
Enter fullscreen mode Exit fullscreen mode

Now we can create a new Person object using our PersonFactory model:

const person = PersonFactory.add("furkan", 24);
console.log(person)
> Output:
> Person { name: 'furkan', age: 24 }
Enter fullscreen mode Exit fullscreen mode

Image description

Abstract Factory

Abstract Factory is a design pattern that we can use when we want to process multiple objects at the same time.

Example: Let's continue with the Person example and create another class named Client derived from the Person class:

class Person {
    consume() {}
}
class Client extends Person {
    consume() {
        console.log("Client")
    }
}
Enter fullscreen mode Exit fullscreen mode

Now let's create factory methods for them and see how abstract is used:

class PersonFactory {
    prepare(name)
}
class ClientFactory extends PersonFactory {
    addClient() {
        console.log("Client created")
        return new Client();
    }
}
Enter fullscreen mode Exit fullscreen mode

Now it's time to use our abstract factory method:

const clientUserFact = new ClientFactory();
const person = clientUserFact.addClient();
person.consume();
> Output:
> Client created
> Client
Enter fullscreen mode Exit fullscreen mode

Image description

Builder

This design allows you to create different types and representations of an object using the same construction code.

Example: Let's continue with our classic Person example. Here we will slightly modify the Person object:

class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    toString() {
        return (
         `${this.name} is ${this.age} years old!`    
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

We use two pieces of information in the Person object: name and age. Now let's define a Person Builder:

class PersonBuilder {
    constructor(person = new Person()) {
        this.person = person;
    }

    get age() {
        return new PersonAgeBuilder(this.person);
    }

    get name(){
        return new PersonNameBuilder(this.person);
    }

    build() {
        return this.person;
    }
}
Enter fullscreen mode Exit fullscreen mode

We said above that our object contains two pieces of information. Now let's create the builders of those objects here:

class PersonNameBuilder extends PersonBuilder {
    constructor(person) {
        super(person)
    }

    is(name) {
        this.person.name = name;
        return this;
    }
}
class PersonAgeBuilder extends PersonBuilder {
    constructor(person) {
        super(person)
    }

    is(age) {
        this.person.age = age;
        return this;
    }
}
Enter fullscreen mode Exit fullscreen mode

Now it's time to use the objects we wrote:

const personBuilder = new PersonBuilder();
const person = personBuilder
                .name.is("Furkan")
                .age.is(24)
                .build();
console.log(person.toString());

> Output:
> Furkan is 24 years old!
Enter fullscreen mode Exit fullscreen mode

Image description

Prototype

Prototype is a design pattern that allows you to copy existing objects without making your code dependent on their classes.

Example: We came to our Person object again :D Here our Person object will be as follows:

class Person {
    constructor(name) {
        this.name = name;
    }

    setName(name) {
        this.name = name;
        console.log(name.toString())
    }

    clone() {
        return new Person(this.name)
    }
}
Enter fullscreen mode Exit fullscreen mode

We said the purpose is to copy and we put a method called clone inside our object. Now let's use this and clone our object:

const person1 = new Person();
person1.setName("furkan");
const person2 = person1.clone();
person2.setName("tugay");

> Output:
> furkan
> tugay
Enter fullscreen mode Exit fullscreen mode

Image description

Singleton

A singleton is used to ensure that there is only one instance of an object and to be called the same everywhere in your code when you need that object.

This is also similar to the “Single Responsibility Principle” in the SOLID principle.

Example: We have come to our last example where we will use the Person object.

class Person {
    constructor() {
        const instance = this.constructor.instance;
        if(instance) {
            return instance;
        }
        this.constructor.instance = this;
    }

    toString() {
        console.log("Person Class");
    }
}
Enter fullscreen mode Exit fullscreen mode

We can also check if singleton is provided in this way:

const person1 = new Person();
const person2 = new Person();
console.log("is same: ", (person1 === person2));
person1.toString();
> Output:
> Person Class
Enter fullscreen mode Exit fullscreen mode

In this article, I talked about what Design Patterns are and tried to explain Creative Patterns with JavaScript codes.

I will share two more articles depending on this article. These:

  • Design Patterns in JavaScript: Structural Patterns
  • Design Patterns in JavaScript: Behavioral Patterns

I hope it was a useful article for you. Don't forget to like and follow me on twitter to support me :D

Top comments (4)

Collapse
 
arashrah profile image
Arash Rahimi

Good article, I enjoyed reading it! If you're interested, feel free to check out my articles as well

Collapse
 
yrombacatan profile image
Jerome Bacatan

helpful

Collapse
 
krlz profile image
krlz

It's a great article Furkan, thanks for sharing

Collapse
 
fruntend profile image
fruntend

Сongratulations 🥳! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up 👍

Some comments have been hidden by the post's author - find out more