Top Design Patterns in Node JS to Master

Posted By : Mohd

Dec 08, 2023

Node.js provides a scalable and efficient platform for highly efficient web and mobile app development. As the usage of Node.js for building backend applications is increasing day by day, it becomes crucial to adopt best practices and design patterns to ensure maintainability, scalability, and code reusability. In this blog post, we will be looking at some of the design patterns that can be implemented to obtain maintainability, scalability, and code reusability.

 

Design Patterns in Node.js

 

Singleton pattern
 

In the singleton design pattern, we make sure that a class has only one instance which is available globally for a whole application. This design pattern can be used when there is a need to control access to some shared resources eg- a database connection or a file. By using this pattern you can avoid unnecessary duplication and improve the efficiency of your application. 

 

Also, Explore | Essentials of Efficient UI/UX Design in Mobile App Development

 

Below is an example of the singleton pattern for a database connection. In this example class, "DatabaseConnection" follows the singleton design pattern and maintains only one instance of the database connection, whenever this class is instantiated, first it checks if an instance is already present, if not then only it creates a new connection to the database otherwise it just returns the already available instance.

 

/**
 * Singleton Pattern - Representing a class for Database connection
 */
class DatabaseConnection {
  constructor(str) {
    // check for instance
    if (!DatabaseConnection.instance) {
      this.connection = // create database connection
      this.testStr = str
      DatabaseConnection.instance = this;
    }
    // return instance
    return DatabaseConnection.instance;
  }
}
// create instance of class
const dbInstance1 = new DatabaseConnection("1");
const dbInstance2 = new DatabaseConnection("2");
console.log(dbInstance1.testStr)
console.log(dbInstance2.testStr)
Output of the above code:
1
1

 

Chain of Responsibility or Middleware pattern


The Middleware pattern is a key element in Node.js frameworks like Express. It involves a chain of functions that process an incoming request and response. Each middleware function has access to the request, response objects, and the next middleware function in the stack. This pattern is excellent for handling tasks such as authentication, logging, and error handling in a modular and reusable way.

 

You may also like | Native vs. Hybrid vs. Web | Choosing Mobile App Development

 

Below is an example of a chain of responsibility pattern implemented using the middleware functionality in Node.js. The code defines two middleware functions "middleware1" and "middleware2" which are used by the "app". Whenever a request comes to our "app" first it passes through "middleware1" and then through "middleware2" before moving to the business logic.

 

/**
 * Middleware Pattern - Representing middleware usage in Node.js
 */

// First middleware
const middleware1 = (req, res, next) => {
  // perform some tasks
  console.log("Inside middleware 1");
  next();
};

// Second middleware
const middleware2 = (req, res, next) => {
  // perform some tasks
  console.log("Inside middleware 2");
  next();
};

app.use(middleware1);
app.use(middleware2);
Output of the above code:
Inside middleware 1
Inside middleware 2

 

Facade pattern:

 
The Facade pattern provides a simple interface to a complex system, hiding its complexities. In Node.js, this can be applied to create a unified API for different modules or subsystems. By doing so, developers can interact with a simplified interface while the underlying complexities are managed behind the scenes.

 

Also, Read |  Cloud-based App Development | A Quintessential Guide

 

Below is an example of facade pattern implementation using a payment gateway class. "PaymentGateway" is a class that implements the functionality of handling payments internally, i.e., the complex processes of verifying a payment or processing the transaction are hidden from the client code, this makes the implementation more robust.

 

/**
 * Facade Pattern - Representing a Payment Gateway that hides its complexities
 */
class PaymentFacade {
  processPayment(amount) {
    // Create an instance of payment gateway
    const paymentGateway = new PaymentGateway();
    // Use the payment gateway to verify payment without knowing the underlying logic
    paymentGateway.verifyPayment();
    paymentGateway.processTransaction(amount);
    return 'Payment successful';
  }
}

 

Observer pattern


In the Observer design pattern an object, known as the subject (publisher), maintains a list of its dependents (subscriber or observer) who subscribe to events from the publisher, they are then informed about these events via different methods from the publisher. This pattern establishes a one-to-many relationship between the subject and its observers, allowing multiple objects to react to the changes in another object without being tightly coupled. 

 

In the below example, the "NewsAgency" is the subject or publisher which publishes news to it's observers, and "NewsReader" instances are observers. When the "NewsAgency" updates its news, all registered observers are notified and respond accordingly.

 

/**
 * Observer Pattern - Representing a News Agency that published news to News Readers
 */
 
// Subject or Publisher
class NewsAgency {
  constructor() {
    // List of observers for this news agency
    this.observers = [];
    this.news = null;
  }

  // Add observers
  addObserver(observer) {
    this.observers.push(observer);
  }

  // Remove observer
  removeObserver(observer) {
    this.observers = this.observers.filter((obs) => obs !== observer);
  }

  // Set News
  setNews(news) {
    this.news = news;
    // Notify the observers about the News
    this.notifyObservers();
  }

  // Notify the observers about the News
  notifyObservers() {
    this.observers.forEach((observer) => observer.update(this.news));
  }
}

// Observer or Subscriber
class NewsReader {
  constructor(name) {
    this.name = name;
  }

  update(news) {
    console.log(`${this.name} received news: ${news}`);
  }
}

// Instance of Publisher
const bbc = new NewsAgency();

// Instances of Subscribers
const john = new NewsReader('John');
const alice = new NewsReader('Alice');

// Add subscirbers to publisher
bbc.addObserver(john);

// Set News which also notifies the subscribers
bbc.setNews('Breaking News: Design patterns in Node.js');
Output of the above code:
John received news: Breaking News: Design patterns in Node.js

 

Conclusion

 

After looking at the above design patterns, now it is time to understand that before applying any design pattern to your application it's important to understand the context, requirement, and scalability of your application and then decide which pattern or a combination of patterns can help you develop the application in a more modular way. In case if you are looking for web and mobile app development, our skilled web and mobile app developers can help you get started quickly. 

Leave a

Comment

Name is required

Invalid Name

Comment is required

Recaptcha is required.

blog-detail

May 3, 2024 at 02:45 am

Your comment is awaiting moderation.

By using this site, you allow our use of cookies. For more information on the cookies we use and how to delete or block them, please read our cookie notice.

Chat with Us
Contact Us

Oodles | Blockchain Development Company

Name is required

Please enter a valid Name

Please enter a valid Phone Number

Please remove URL from text