📡 You're offline — showing cached content
New version available!
Quick Access
SQL Advanced

JavaScript Design Patterns: Observer, Module, Proxy and Strategy

Master JavaScript design patterns — Module (IIFE), Observer (pub/sub), Proxy for intercept, Strategy for algorithm swapping.

EzyCoders Admin November 23, 2025 12 min read 0 views
JavaScript Design Patterns Observer Module Proxy
Share: Twitter LinkedIn WhatsApp

JavaScript Design Patterns

Design patterns in JavaScript solve recurring architecture problems. The language's flexibility enables multiple pattern implementations, and interviewers at senior level expect you to know and explain them.

// ── Module Pattern — private scope ───────────────────────────────
const UserStore = (() => {
    const users = [];  // private

    return {
        add: (user) => users.push(user),
        get: (id)   => users.find(u => u.id === id),
        count: ()   => users.length,
    };
})();

UserStore.add({id: 1, name: 'Rahul'});
console.log(UserStore.count()); // 1
console.log(UserStore.users);   // undefined (private!)

// ── Observer (Pub/Sub) ────────────────────────────────────────────
class EventEmitter {
    #events = {};

    on(event, fn) {
        (this.#events[event] ??= []).push(fn);
        return () => this.off(event, fn); // unsubscribe fn
    }

    off(event, fn) {
        this.#events[event] = this.#events[event]?.filter(f => f !== fn);
    }

    emit(event, ...args) {
        this.#events[event]?.forEach(fn => fn(...args));
    }
}

const bus = new EventEmitter();
const unsub = bus.on('userLogin', user => console.log(`${user.name} logged in`));
bus.emit('userLogin', {name: 'Rahul'}); // Rahul logged in
unsub(); // remove listener
// ── Proxy Pattern — intercept operations ─────────────────────────
const handler = {
    get(target, prop) {
        console.log(`Getting: ${prop}`);
        return prop in target ? target[prop] : `${prop} not found`;
    },
    set(target, prop, value) {
        if (prop === 'age' && typeof value !== 'number') {
            throw new TypeError('age must be a number');
        }
        target[prop] = value;
        return true;
    }
};

const user = new Proxy({}, handler);
user.name = 'Rahul';  // sets ok
user.age  = '25';     // TypeError: age must be a number
console.log(user.name);  // Getting: name → 'Rahul'

// ── Strategy Pattern ──────────────────────────────────────────────
const sorters = {
    bubble:    (arr) => [...arr].sort((a,b) => a-b),  // simplified
    selection: (arr) => [...arr].sort((a,b) => a-b),
    quick:     (arr) => [...arr].sort((a,b) => a-b),
};

class Sorter {
    setStrategy(name) { this.fn = sorters[name]; }
    sort(arr)         { return this.fn(arr); }
}

const s = new Sorter();
s.setStrategy('quick');
console.log(s.sort([3,1,4,1,5])); // [1,1,3,4,5]

Q: What is the difference between Observer and Pub/Sub?

In the Observer pattern, subjects and observers know about each other directly — observers register on the subject object. In Pub/Sub, publishers and subscribers are decoupled through an event bus/broker — publishers and subscribers never reference each other directly. Pub/Sub is more loosely coupled and suitable for cross-module communication.

EzyCoders Admin
Written by
EzyCoders Admin

Team Lead and Full-Stack Developer with experience in PHP, JavaScript, SQL, DSA, and System Design. Passionate about software engineering, scalable web technologies, and helping developers prepare for coding interviews and tech careers through practical tutorials and professional guidance.

Comments (0)

No comments yet. Be the first!

Leave a Comment