Home Web Front-end JS Tutorial Five Design Patterns to know in Node.js

Five Design Patterns to know in Node.js

Oct 07, 2024 pm 06:17 PM

Hey there!

I recently went through multiple knowledge resources to learn more about popular design and architectural patterns in Node.js. My aim was mainly at the server (backend) side but as I was going through them, I was seeing a lot of similarities to the browser (frontend) frameworks. Some of them are even directly used in the frameworks for which I am even more happy because I was using them already without knowing it ?

There are many (really many) design patterns that you could use, so in this article, I decided to choose 10 of them and explain them in more detail.

Enjoy!

? What is a Design Pattern?

Design patterns are proven and battle-tested solutions to solve problems that we as developers encounter every day. These patterns help promote best practices and implement a structured approach to solving everyday issues while designing and developing software architecture. Software engineers can develop maintainable, secure, and stable systems by using these patterns.

Node.js due to its flexibility does not force you to stick to certain patterns but instead gives you the freedom of choosing just the ones needed for your task. That is why in my opinion it is so widely used today (and by the way thanks to JavaScript :D).

✅ Five Popular Design Patterns in Node.js

Below, you will see a list of 5 selected design patterns that I like.

Singleton

This pattern is all about classes that can have only one instance and provide global access to it. Modules can be cached and shared across the application in Node.js which will help improve the efficiency of resources. A common example of such a singleton pattern is a module for connecting with certain third-party services like databases, cache services, email providers, etc that is used extensively in the Nest.js framework. Let's take a look at the following example:


class Redis {
  constructor() {
    this.connection = null;
  }

  static getInstance() {
    if (!Redis. instance) {
      Redis.instance = new Redis(options);
    }

    Return Redis.instance;
  }

  connect() {
    this.connection = 'Redis connected'
  }
}


Copy after login

And then we can use it like the following:


const medicine = Redis.getInstance();
const redisTwo = Redis.getInstance();

console.log(redisOne === RedisTwo); // it will result to `true`

redisOne.connect();

console.log(redisOne.connection) // 'Redis connected'
console.log(redisTwo.connection) // 'Redis connected'


Copy after login

This approach ensures that there is only one connection to Redis and prevents duplicating connections.

Factory

With this pattern, you can create new objects without specifying the class of object that will be created. Thanks to it we are abstracting object creation which can help improve code readability and reusability:


class Character {
  constructor(name, health) {
    this.name = name;
    this.health = health;
  }
}

class CharacterFactory {
  createCharacter(name) {
    switch(name) {
      case 'mage': 
        return new Character('Powerful Mage', 8);
      case 'warrior':
        return new Character('Courageous Warrior', 10);
      case 'rogue':
        return new Character('Sneaky Rogue', 9)
      default:
        return new Error('Unknown character');
    }
  }
}


Copy after login

And then we can use it like the following:


const characterFactory = new CharacterFactory();

const mage = characterFactory.createCharacter('mage');
const warrior = characterFactory.createCharacter('warrior');

console.log(mage.name) // Powerful Mage
console.log(warrior.name) // Courageous Warrior


Copy after login

This approach allows consumers of this factory to use the factory code instead of using the Character class constructor directly.

Observer

This pattern works in a way that you will have an entity that manages the list of depending elements called observers and notifies them if the state changes. This pattern is used widely in the Vue.js framework and be implemented like this:


class Topic {
  constructor() {
    this.observers = []; 
  }

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

  unsubscribe(observer) {
    this.observers = this.observers.filter(o => o !== observer);
  }

  notify(data) {
    this.observers.forEach(o => o.update(data));
  }
}

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

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


Copy after login

And you can use it like the following:


const topic = new Topic();

const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');

topic.subscribe(observer1);
topic.subscribe(observer2);

topic.notify('Hello World');
// Observer 1 received Hello World 
// Observer 2 received Hello World

topic.unsubscribe(observer2);

topic.notify('Hello Again');
// Observer 1 received Hello Again


Copy after login

It is a really useful pattern for event handling and asynchronous workflows that allows to update of multiple objects without coupling the publisher to the subscribers.

Decorator

This pattern is quite useful for extending the existing functionality with a new one without affecting the initial/original instances. It is used widely in the Nest.js framework thanks to the full support of TypeScript but in regular Node.js it can be used in following:


class Character {
  constructor() {
    this.endurance = 10;
  }

  getEndurance() {
    return this.endurance;
  }
}

class CharacterActions {
  constructor(character) {
    this.character = character;
  }

  attack() {
    this.character.endurance -= 2;
  }

  rest() {
    this.character.endurance += 1; 
  }
}


Copy after login

And then it can be used like the following:


const character = new Character();

console.log(character.getEndurance()); // 10

const characterWithActions = new CharacterActions(character);

characterWithActions.attack(); // - 2
characterWithActions.rest(); // + 1

console.log(characterWithActions.character.getEndurance()); // 9


Copy after login

By using this pattern we can easily extend already existing classes without affecting their core functionality.

Dependency Injection

In this pattern, classes or modules receive dependencies from external sources rather than registering them internally. This approach allows extracting certain reusable elements from your system for easier testing and maintenance. It is used quite extensively in the Nest.js framework. It can be implemented like following:


class UserService {
  constructor(databaseService, loggerService) {
    this.db = databaseService;
    this.logger = loggerService;
  }

  async getUser(userId) {
    const user = await this.db.findUserById(userId);
    this.logger.log(`Fetched user ${user.name}`);
    return user;
  }
}


Copy after login

And then, you can use it like following:


const databaseService = new Database();
const loggerService = new Logger();

const userService = new UserService(databaseService, loggerService);

userService.getUser(1);


Copy after login

This approach allows you to extract elements of your system into intependent entities that can be injected when needed.

? Learn more

If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, check VueSchool by clicking this link or by clicking the image below:

Five Design Patterns to know in Node.js

It covers the most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects ?

✅ Summary

Well done! You have just learned how certain design patterns work in Node.js and how to implement them.

Take care and see you next time!

And happy coding as always ?️

The above is the detailed content of Five Design Patterns to know in Node.js. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat Commands and How to Use Them
1 months ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How do I create and publish my own JavaScript libraries? How do I create and publish my own JavaScript libraries? Mar 18, 2025 pm 03:12 PM

Article discusses creating, publishing, and maintaining JavaScript libraries, focusing on planning, development, testing, documentation, and promotion strategies.

How do I optimize JavaScript code for performance in the browser? How do I optimize JavaScript code for performance in the browser? Mar 18, 2025 pm 03:14 PM

The article discusses strategies for optimizing JavaScript performance in browsers, focusing on reducing execution time and minimizing impact on page load speed.

What should I do if I encounter garbled code printing for front-end thermal paper receipts? What should I do if I encounter garbled code printing for front-end thermal paper receipts? Apr 04, 2025 pm 02:42 PM

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

How do I debug JavaScript code effectively using browser developer tools? How do I debug JavaScript code effectively using browser developer tools? Mar 18, 2025 pm 03:16 PM

The article discusses effective JavaScript debugging using browser developer tools, focusing on setting breakpoints, using the console, and analyzing performance.

Who gets paid more Python or JavaScript? Who gets paid more Python or JavaScript? Apr 04, 2025 am 12:09 AM

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

How do I use source maps to debug minified JavaScript code? How do I use source maps to debug minified JavaScript code? Mar 18, 2025 pm 03:17 PM

The article explains how to use source maps to debug minified JavaScript by mapping it back to the original code. It discusses enabling source maps, setting breakpoints, and using tools like Chrome DevTools and Webpack.

The difference in console.log output result: Why are the two calls different? The difference in console.log output result: Why are the two calls different? Apr 04, 2025 pm 05:12 PM

In-depth discussion of the root causes of the difference in console.log output. This article will analyze the differences in the output results of console.log function in a piece of code and explain the reasons behind it. �...

How to merge array elements with the same ID into one object using JavaScript? How to merge array elements with the same ID into one object using JavaScript? Apr 04, 2025 pm 05:09 PM

How to merge array elements with the same ID into one object in JavaScript? When processing data, we often encounter the need to have the same ID...

See all articles