JavaScript Design Patterns: Explained with Examples


What Are Design Patterns?

Design patterns are reusable solutions to common programming problems. They help you write clean, maintainable, and scalable JavaScript code by following time-tested architecture.



Types of JavaScript Design Patterns

1. Creational Patterns – For creating objects

2. Structural Patterns – For organizing code and relationships

3. Behavioral Patterns – For communication between objects



1. Creational Patterns


a) Constructor Pattern

Used to create multiple instances of an object with the same structure.

function Person(name, age) {
this.name = name;
this.age = age;
}
const person1 = new Person("Alice", 25);

Use case: Creating similar objects efficiently.



b) Factory Pattern

Creates objects without specifying the exact class.

function createUser(role) {
if (role === "admin") {
return { role, permissions: "all" };
} else {
return { role, permissions: "limited" };
}
}
const admin = createUser("admin");

Use case: When object creation needs to be flexible.



c) Singleton Pattern

Restricts instantiation to one object only.

const Singleton = (function () {
let instance;
function createInstance() {
return { id: Date.now() };
}
return {
getInstance: function () {
if (!instance) instance = createInstance();
return instance;
},
};
})();
const obj1 = Singleton.getInstance();
const obj2 = Singleton.getInstance();
console.log(obj1 === obj2); // true

Use case: Managing shared resources (e.g., DB connection).



2. Structural Patterns


a) Module Pattern

Encapsulates private variables/functions.

const CounterModule = (function () {
let count = 0;
return {
increment() {
count++;
console.log(count);
},
reset() {
count = 0;
},
};
})();
CounterModule.increment(); // 1
CounterModule.increment(); // 2

Use case: Data privacy and encapsulation.



b) Decorator Pattern

Adds new functionality to existing objects.

function vehicle() {
this.drive = () => console.log("Driving");
}
function turbo(vehicle) {
vehicle.turboBoost = () => console.log("Turbo Mode");
return vehicle;
}
const car = turbo(new vehicle());
car.drive(); // Driving
car.turboBoost(); // Turbo Mode

Use case: Enhancing object functionality.



3. Behavioral Patterns


a) Observer Pattern

When one object (subject) updates, observers are notified.

class Subject {
constructor() {
this.observers = [];
}
subscribe(fn) {
this.observers.push(fn);
}
notify(data) {
this.observers.forEach((fn) => fn(data));
}
}
const news = new Subject();
news.subscribe((data) => console.log("News Update:"
, data));
news.notify("New article published");

Use case: Reactivity systems, pub/sub (e.g., event handling).



b) Command Pattern

Encapsulates a request as an object.

function lightOn() {
console.log("Light turned ON");
}
function lightOff() {
console.log("Light turned OFF");
}
function execute(fn) {
fn();
}
execute(lightOn); // Light turned ON

Use case: Queued commands, undo/redo functionality.


c) Strategy Pattern

Defines different algorithms as interchangeable objects.

function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
function calculate(a, b, strategy) {
return strategy(a, b);
}
console.log(calculate(10, 5, add)); // 15
console.log(calculate(10, 5, subtract)); // 5

Use case: Switching between multiple strategies dynamically.



Summary Table

Pattern Type Pattern Use Case Example
Creational Singleton Logging system, DB connection
Creational Factory UI components
Structural Module Encapsulation, private data
Structural Decorator Add methods to an object
Behavioral Observer Event listeners, pub/sub
Behavioral Strategy Dynamic algorithm switching