Skip to main content
Course/Module 12/Topic 1 of 4Advanced

Design Patterns in Node.js

Learn essential design patterns for Node.js applications including Singleton, Factory, Observer, and Module patterns.

90 min•By Priygop Team•Last updated: Feb 2026

Singleton Pattern

Ensure a class has only one instance and provide global access to it.

Factory Pattern

Example
// Factory pattern for creating objects
class DatabaseConnectionFactory {
    static createConnection(type) {
        switch (type) {
            case 'mysql':
                return new MySQLConnection();
            case 'postgresql':
                return new PostgreSQLConnection();
            case 'mongodb':
                return new MongoDBConnection();
            default:
                throw new Error('Unsupported database type');
        }
    }
}

class MySQLConnection {
    connect() {
        console.log('Connecting to MySQL');
    }
}

class PostgreSQLConnection {
    connect() {
        console.log('Connecting to PostgreSQL');
    }
}

// Usage
const db = DatabaseConnectionFactory.createConnection('mysql');
db.connect();

Observer Pattern

Example
// Event-driven architecture with Observer pattern
class EventEmitter {
    constructor() {
        this.events = {};
    }
    
    on(event, listener) {
        if (!this.events[event]) {
            this.events[event] = [];
        }
        this.events[event].push(listener);
    }
    
    emit(event, data) {
        if (this.events[event]) {
            this.events[event].forEach(listener => listener(data));
        }
    }
}

// Usage
const emitter = new EventEmitter();
emitter.on('user:created', (user) => {
    console.log('User created:', user);
});
emitter.emit('user:created', { id: 1, name: 'John' });

Module Pattern

Example
// Module pattern for encapsulation
const UserModule = (() => {
    let users = [];
    
    return {
        addUser: (user) => {
            users.push(user);
        },
        getUsers: () => [...users],
        getUserById: (id) => users.find(u => u.id === id)
    };
})();

// Usage
UserModule.addUser({ id: 1, name: 'John' });
console.log(UserModule.getUsers());

strategy Pattern

Example
// strategy pattern for different algorithms
class PaymentProcessor {
    constructor(strategy) {
        this.strategy = strategy;
    }
    
    processPayment(amount) {
        return this.strategy.process(amount);
    }
}

class CreditCardStrategy {
    process(amount) {
        return `Processing ${amount} via Credit Card`;
    }
}

class PayPalStrategy {
    process(amount) {
        return `Processing ${amount} via PayPal`;
    }
}

// Usage
const processor = new PaymentProcessor(new CreditCardStrategy());
console.log(processor.processPayment(100));

Mini-Project: Complete Pattern Implementation

Example
// Complete design patterns implementation
class Logger {
    constructor() {
        if (Logger.instance) {
            return Logger.instance;
        }
        this.logs = [];
        Logger.instance = this;
    }
    
    log(message) {
        const timestamp = new Date().toISOString();
        this.logs.push({ message, timestamp });
        console.log(`[${timestamp}] ${message}`);
    }
    
    getLogs() {
        return this.logs;
    }
}

// Factory for different types of handlers
class HandlerFactory {
    static createHandler(type) {
        switch (type) {
            case 'email':
                return new EmailHandler();
            case 'sms':
                return new SMSHandler();
            case 'push':
                return new PushHandler();
            default:
                throw new Error('Unknown handler type');
        }
    }
}

class EmailHandler {
    send(message) {
        console.log(`Sending email: ${message}`);
    }
}

class SMSHandler {
    send(message) {
        console.log(`Sending SMS: ${message}`);
    }
}

// Observer pattern for notifications
class NotificationService {
    constructor() {
        this.subscribers = [];
    }
    
    subscribe(callback) {
        this.subscribers.push(callback);
    }
    
    notify(data) {
        this.subscribers.forEach(callback => callback(data));
    }
}

// Usage
const logger = new Logger();
const notificationService = new NotificationService();

notificationService.subscribe((data) => {
    logger.log(`Notification sent: ${data.message}`);
});

const emailHandler = HandlerFactory.createHandler('email');
emailHandler.send('Welcome to our service!');

šŸ“š Additional Resources

Recommended Reading

  • • Node.js Design Patterns Guide
  • • Advanced Debugging Techniques
  • • Error Handling Best Practices
  • • Production Deployment Guide

Online Resources

  • • Node.js Performance Optimization
  • • Debugging Node.js Applications
  • • Production Best Practices
  • • Node.js security Guide
Chat on WhatsApp
Priygop - Leading Professional Development Platform | Expert Courses & Interview Prep