DEV Community

Cover image for Master the Top 5 Essential JavaScript Design Patterns Every Developer Should Know
Hoài Nhớ ( Nick )
Hoài Nhớ ( Nick )

Posted on

3 3 3 3 3

Master the Top 5 Essential JavaScript Design Patterns Every Developer Should Know

1. Singleton Pattern

Image description

What is it?

A design pattern that restricts the instantiation of a class to a single instance.

When was it created?

Introduced as part of the GoF (Gang of Four) design patterns in 1994.

Node.js Support:

All versions of Node.js.

Why use it?

Prevents multiple instances and manages global state efficiently.

Best Practices:

• Use it for shared configurations or resource-heavy classes.

Example:

class Singleton {
  static instance;
  constructor() {
    if (!Singleton.instance) {
      Singleton.instance = this;
    }
    return Singleton.instance;
  }
}
const singletonA = new Singleton();
const singletonB = new Singleton();
console.log(singletonA === singletonB); // true
Enter fullscreen mode Exit fullscreen mode

Pros:

• Global access point.

• Easy to manage shared state.

Cons:

• Harder to test and refactor due to global reliance.

2. Factory Pattern

What is it?

Encapsulates object creation logic, returning objects from a shared interface.

When was it created?

Another GoF pattern from the 1990s.

Node.js Support:

Supported across all versions.

Why use it?

Simplifies complex object creation.

Best Practices:

• Useful when dealing with large-scale applications needing multiple object types.

Example:

class Car {
  constructor(model) { this.model = model; }
}
class CarFactory {
  createCar(type) {
    switch(type) {
      case 'sedan': return new Car('Sedan');
      case 'suv': return new Car('SUV');
      default: return null;
    }
  }
}
const factory = new CarFactory();
const sedan = factory.createCar('sedan');
console.log(sedan.model); // 'Sedan'
Enter fullscreen mode Exit fullscreen mode

Pros:

• Encapsulates object creation logic.

• Supports easy object extension.

Cons:

• Overhead for simple objects.

3. Observer Pattern

What is it?

Allows one object (subject) to notify observers about state changes.

When was it created?

First formalized in the 1970s; adopted into JS in event-driven systems.

Node.js Support:

Supported by event-driven architecture.

Why use it?

Ideal for decoupling objects in event-based systems.

Best Practices:

• Use it in pub/sub messaging systems.

Example:

class Observer {
  update(data) { console.log(`Observer received: ${data}`); }
}
class Subject {
  constructor() { this.observers = []; }
  addObserver(observer) { this.observers.push(observer); }
  notify(data) { this.observers.forEach(o => o.update(data)); }
}
const subject = new Subject();
const observer = new Observer();
subject.addObserver(observer);
subject.notify('Event Fired'); // Observer received: Event Fired
Enter fullscreen mode Exit fullscreen mode

Pros:

• Promotes loose coupling.

Cons:

• Can be complex to manage with many observers.

4. Strategy Pattern

What is it?

Encapsulates algorithms and allows them to be interchangeable within a class.

When was it created?

Part of GoF’s 1994 design patterns.

Node.js Support:

Supported in all modern versions.

Why use it?

Allows flexibility by changing algorithms dynamically.

Best Practices:

• Ideal for scenarios requiring multiple approaches to the same problem.

Example:

class Context {
  setStrategy(strategy) { this.strategy = strategy; }
  executeStrategy(a, b) { return this.strategy.doOperation(a, b); }
}
class Add {
  doOperation(a, b) { return a + b; }
}
class Subtract {
  doOperation(a, b) { return a - b; }
}
const context = new Context();
context.setStrategy(new Add());
console.log(context.executeStrategy(5, 3)); // 8
context.setStrategy(new Subtract());
console.log(context.executeStrategy(5, 3)); // 2
Enter fullscreen mode Exit fullscreen mode

Pros:

• Easy to switch algorithms.

Cons:

• Increases class complexity.

5. Decorator Pattern

What is it?

Dynamically adds responsibilities to objects.

When was it created?

From GoF’s pattern library.

Node.js Support:

Supported in all versions with ES6 classes.

Why use it?

Provides flexible object functionality without subclassing.

Best Practices:

• Use it for adding extra features or responsibilities to objects.

Example:

class Car {
  getDescription() { return 'Car'; }
}
class SportsCarDecorator {
  constructor(car) { this.car = car; }
  getDescription() { return `${this.car.getDescription()} with sports package`; }
}
const car = new Car();
const sportsCar = new SportsCarDecorator(car);
console.log(sportsCar.getDescription()); // 'Car with sports package'
Enter fullscreen mode Exit fullscreen mode

Pros:

• Extends functionality dynamically.

Cons:

• Can make the code harder to read if overused.


© 2024 HoaiNho — Nick, Software Engineer. All rights reserved.

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs