The Talent500 Blog
5 JavaScript design patterns every developer should try 1

5 JavaScript design patterns every developer should try

A good JavaScript developer knows how to write clean, healthy, and maintainable code. In your career, you will work on numerous projects, but some relevant traits will serve you well irrespective of the project you are working on. Writing clean code is essential for JavaScript developers, and design patterns can help.

Design patterns are reusable solutions that are made and tested by a large number of developers to solve some of the most common problems that occur during software development. Due to the combined experience of many developers, design patterns help write optimized code.

In this article, we will list some widely used JavaScript design patterns

Singleton Pattern

One of the most well-known JavaScript design patterns, the Singleton pattern is used to define a class that is restricted only to one instance and can be accessed globally. It is a super helpful JavaScript design when you need a feature to handle specific tasks from anywhere in the application.

That being said, you must be careful with Singleton patterns as they can make it challenging to test the code.

Sample code:

 

const utils = (function () {

  let instance;

   function initialize() {

   return {

    sum: function (a, b) {

     return a + b;

    }

   };

  }  

return {

   getInstance: function () {

    if (!instance) {

     instance = initialize();

    }   

return instance;

   }

  };

 })();

let sum = utils.getInstance().sum(3, 5); // 8

Constructor Pattern

In JavaScript, constructors are essential concepts. They are the functions that initialize objects with specific methods and properties. A constructor pattern is used to write clean JavaScript code when using multiple instances of the same object in the code.

Look at the following JavaScript design where the constructor pattern is used for the ‘let person’ object.

// Creating empty object using {}:

 let person = {};

// Using Object() to create empty objects:

 let person = new Object();

// Using function constructor:

 function Person(name, age) {

  this.name = name;

  this.age = age;

  this.showName = () => console.log(this.name);

 }

let person = new Person(‘Amy’, 28);

 person.showName();

Command Pattern

You can encapsulate actions or operations as objects in JavaScript using a command pattern.

Let us understand it with an example. Suppose you are working on an eCommerce project and building its payment feature in JavaScript. You can do it in multiple ways. If there is a specific payment method, you can use:

if (selectedPayment == ‘credit card’) {

  // handle payment by creditcard

 }

However, ideally any eCommerce project will have multiple payment options. In the code above, you are using a tight coupling, i.e. coding classes and objects to depend on one another.

The command pattern can be used here as an easy way to provide loose coupling, reducing the interdependencies between components of the code. Learn more about tight and loose coupling here.

The system need not know about the information of each payment method processing, so an optimal solution is to break the overall process into two parts using a command pattern – the code that requests an operation and the code that executes the payment method.

Here is an example of a command pattern:

function Command(operation) {

  this.operation = operation;

 }Command.prototype.execute = function () {

  this.operation.execute();

 }function ProcessCreditCardPayment() {

  return {

  execute: function() {

   console.log(‘Credit Card’)

   }

  };

 }function ProcessPayPalPayment() {

  return {

   execute: function() {

   console.log(‘PayPal’)

   }

  };

 }function ProcessStripePayment() {

  return {

   execute: function() {

   console.log(‘Stripe’)

   }

  };}function CreditCardCommand() {

  return new Command(new ProcessCreditCardPayment());

 }function PayPalCommand() {

  return new Command(new ProcessPayPalPayment());

 }function StripeCommand() {

  return new Command(new ProcessStripePayment());

 }function PaymentSystem() {

  let paymentCommand;

    return {

   setPaymentCommand: function(command) {

    paymentCommand = command;

   },

   executeCommand: function() {

   paymentCommand.execute();

   }

  };

 }function run() {

  let paymentSystem = new PaymentSystem();

  paymentSystem.setPaymentCommand(new CreditCardCommand());

  paymentSystem.executeCommand();

  paymentSystem.setPaymentCommand(new PayPalCommand());

  paymentSystem.executeCommand();

  paymentSystem.setPaymentCommand(new StripeCommand());

  paymentSystem.executeCommand();

 }run();

Module Pattern

The module pattern is another JavaScript design concept usually used in web development for implementing software modules. If you look at the code inside a JavaScript library, you will find module patterns are used as singleton objects. Using module pattern, you can make variables, functions, and properties inside a module public or private to create the most robust web applications.

Example:

const bookModule = (function() {

  // private

  let title = ‘JavaScript’;

  let price = 15; // public

  return {

   printTitle: function () {

    console.log(title);

   }

  }

 })();

bookModule.printTitle(); // JavaScript

Mediator Pattern

When designing decoupled systems, a mediator pattern is used when you need different parts of the system to communicate with each other in a coordinated manner.

In simple terms, the Mediator pattern provides central authority over a group of objects or functions by encapsulating how these objects interact.

Here is an example of a chatroom with four participants, where the Chatroom is the Mediator and each participant is identified by the Participant object.

var Participant = function (name) {

   this.name = name;

   this.chatroom = null;

};

 Participant.prototype = {

   send: function (message, to) {

  this.chatroom.send(message, this, to);

   },

   receive: function (message, from) {

    console.log(from.name + ” to ” + this.name + “: ” + message);

   }

};

 var Chatroom = function () {

  var participants = {};

  return {

 register: function (participant) {

 participants[participant.name] = participant;

  participant.chatroom = this;

     },

 send: function (message, from, to) {

       if (to) { // single message

  to.receive(message, from);

       } else { // broadcast message

         for (key in participants) {

           if (participants[key] !== from) {

 participants[key].receive(message, from);

           }

         }

       }

     }

   };

};

 function run() {

  var yoko = new Participant(“Yoko”);

   var john = new Participant(“John”);

   var paul = new Participant(“Paul”);

  var ringo = new Participant(“Ringo”);

 var chatroom = new Chatroom();

 chatroom.register(yoko);

 chatroom.register(john);

 chatroom.register(paul);

 chatroom.register(ringo);

 Yoko.send(“All you need is love.”);

  Yoko.send(“I love you John.”);

  john.send(“Hey, no need to broadcast”, yoko);

  paul.send(“Ha, I heard that!”);

  Ringo.send(“Paul, what do you think?”, paul);

}

Conclusion

In the beginning, you might struggle to apply design patterns to your projects, but with practice, you can master them.

Why put in the effort, you ask? Because once you fully understand JavaScript design patterns, you will know what pattern to use in your project. It will take your code to the most robust level.

Talent500 is the platform for JavaScript developers to find career redefining opportunities with global companies. Join our elite pool of talent here.

 

0
Manik Sharma

Manik Sharma

Manik Sharma specializes primarily in UI or Software Development using Javascript libraries like React and Redux along with HTML, CSS, and other libraries like Bootstrap, Node.js, Express.js, MongoDB. He loves to talk business and think of cool startup ideas. Definitely, an entrepreneur in making. He is equally interested in discussing innovative ideas that can make a huge difference in someone's life.

Add comment