💡 Running Code Locally: While this online editor runs real JavaScript, some advanced examples may have limitations. For the best experience:

    • Download Node.js to run JavaScript on your computer
    • Use your browser's Developer Console (Press F12) to test code snippets
    • Create a .html file with <script> tags and open it in your browser

    Advanced Design Patterns in JavaScript

    Master Factory, Singleton, Strategy, Observer, Decorator, and Facade patterns for scalable applications

    What You'll Learn

    • Factory Pattern
    • Singleton Pattern
    • Strategy Pattern
    • Observer Pattern
    • Decorator Pattern
    • Facade Pattern

    Design patterns are reusable solutions for common problems in JavaScript applications. They are not "copy/paste code" — they're mental tools to structure your app cleanly so it's easier to extend, debug, maintain, test, and scale. Every professional developer uses patterns daily.

    ⭐ The 3 Core Pattern Categories

    1. Creational

    Object creation: Factory, Singleton, Builder, Prototype

    2. Structural

    Object relationships: Adapter, Facade, Decorator, Proxy

    3. Behavioral

    Object behaviour: Strategy, Observer, Command, State

    ⭐ 1. Factory Pattern

    Creates objects without exposing the creation logic. Use when object creation depends on input or you need different classes based on conditions.

    Factory Pattern

    Create objects without exposing creation logic

    Try it Yourself »
    JavaScript
    class User {
      constructor(name, permissions) {
        this.name = name;
        this.permissions = permissions;
      }
    }
    
    const roleMap = {
      basic: ["read"],
      pro: ["read", "write"],
      admin: ["read", "write", "delete"],
    };
    
    class UserFactory {
      static create(name, role) {
        const permissions = roleMap[role];
        return new User(name, permissions);
      }
    }
    
    const admin = UserFactory.create("Alice", "admin");
    console.log(admin.name, admin.permissions);
    
    const basic = UserFactory.create("Bob", "basic");
    ...

    Use when: Creation logic is variable, many object types

    Avoid when: Only one type exists, simple creation

    ⭐ 2. Singleton Pattern

    Ensures only one instance of a class exists throughout the app. Perfect for configuration, database connections, logging, caching, or global state.

    Singleton Pattern

    Ensure only one instance exists

    Try it Yourself »
    JavaScript
    class AppConfig {
      constructor() {
        if (AppConfig.instance) return AppConfig.instance;
    
        this.env = "production";
        this.cacheEnabled = true;
        this.theme = "dark";
    
        AppConfig.instance = this;
      }
    
      setOption(key, value) {
        this[key] = value;
      }
    }
    
    const cfg1 = new AppConfig();
    const cfg2 = new AppConfig();
    
    console.log("Same instance?", cfg1 === cfg2); // true
    
    cfg1.setOption("theme", "light");
    console.log("cfg2 theme:", cfg2.theme); // "light" (same object!)
    
    // Pro tip: fr
    ...

    ⚠️ Warning: Don't use Singletons for user-specific data, UI state, or anything that should reset per page/component.

    ⭐ 3. Strategy Pattern

    Switch between different algorithms without rewriting code. Your anti-if/else superpower for payment methods, sorting, filters, shipping rules, etc.

    Strategy Pattern

    Switch between different algorithms

    Try it Yourself »
    JavaScript
    // Strategy classes
    class Paypal { 
      pay(amount) { 
        console.log("PayPal payment:", amount); 
        return true;
      } 
    }
    
    class Card { 
      pay(amount) { 
        console.log("Card payment:", amount); 
        return true;
      } 
    }
    
    class Crypto { 
      pay(amount) { 
        console.log("Crypto payment:", amount); 
        return true;
      } 
    }
    
    // Strategy registry
    const strategies = {
      paypal: new Paypal(),
      card: new Card(),
      crypto: new Crypto(),
    };
    
    // Clean usage
    function processPayment(method, amount) {
      co
    ...

    ⭐ 4. Observer Pattern

    One event, many listeners. Used in UI frameworks, WebSockets, pub/sub systems, notifications, and data stores.

    Observer Pattern

    One event, many listeners

    Try it Yourself »
    JavaScript
    class EventBus {
      constructor() {
        this.listeners = {};
      }
    
      on(event, callback) {
        if (!this.listeners[event]) this.listeners[event] = [];
        this.listeners[event].push(callback);
      }
    
      off(event, callback) {
        if (!this.listeners[event]) return;
        this.listeners[event] = this.listeners[event].filter(cb => cb !== callback);
      }
    
      emit(event, payload) {
        if (this.listeners[event]) {
          this.listeners[event].forEach(cb => cb(payload));
        }
      }
    }
    
    // Usage
    const bus = new E
    ...

    ⭐ 5. Decorator Pattern

    Add features to an object without changing its original code. Perfect for logging, caching, authentication checks, retry logic, and performance measurement.

    Decorator Pattern

    Add features without changing original code

    Try it Yourself »
    JavaScript
    // Logging decorator
    function withLogging(fn) {
      return function(...args) {
        console.log("[LOG] Calling with args:", args);
        const result = fn(...args);
        console.log("[LOG] Result:", result);
        return result;
      };
    }
    
    // Timing decorator
    function withTiming(fn) {
      return function(...args) {
        const start = performance.now();
        const result = fn(...args);
        const end = performance.now();
        console.log("[TIMING] Execution time:", (end - start).toFixed(2), "ms");
        return resu
    ...

    ⭐ 6. Facade Pattern

    Simplifies complex systems behind a clean API. Hide ugly complexity from users of your code.

    Facade Pattern

    Simplify complex systems behind a clean API

    Try it Yourself »
    JavaScript
    // Complex subsystems
    class EmailService {
      send(to, msg) { console.log("Email to", to + ":", msg); }
    }
    
    class SmsService {
      send(to, msg) { console.log("SMS to", to + ":", msg); }
    }
    
    class PushService {
      send(to, msg) { console.log("Push to", to + ":", msg); }
    }
    
    // Facade - clean interface
    class NotificationFacade {
      constructor() {
        this.email = new EmailService();
        this.sms = new SmsService();
        this.push = new PushService();
      }
    
      notify(type, to, message) {
        switch(type) {
    
    ...

    ⭐ Real-World Example: Authentication System Using 4 Patterns

    Combining Strategy + Factory + Decorator + Singleton for a professional login system.

    Authentication System Using 4 Patterns

    Strategy + Factory + Decorator + Singleton combined

    Try it Yourself »
    JavaScript
    // STRATEGY: Different login methods
    class PasswordLogin {
      login(data) { 
        console.log("Password login for:", data.email); 
        return { success: true, method: "password" };
      }
    }
    
    class GoogleLogin {
      login(data) { 
        console.log("Google OAuth for token:", data.token); 
        return { success: true, method: "google" };
      }
    }
    
    class GithubLogin {
      login(data) { 
        console.log("GitHub OAuth for token:", data.token); 
        return { success: true, method: "github" };
      }
    }
    
    // FACTORY: Sele
    ...

    ⭐ Refactoring: Switch Statement → Patterns

    Turning messy code into clean, extensible architecture.

    Refactoring: Switch Statement → Patterns

    Turn messy code into clean architecture

    Try it Yourself »
    JavaScript
    // ❌ BEFORE: Messy switch statement
    function handleEventBad(event) {
      switch (event.type) {
        case "order": console.log("Processing order..."); break;
        case "refund": console.log("Processing refund..."); break;
        case "cancel": console.log("Cancelling..."); break;
        default: console.log("Unknown event");
      }
    }
    
    // ✔ AFTER: Strategy + Factory pattern
    class OrderEvent { 
      run(data) { console.log("Processing order:", data); } 
    }
    class RefundEvent { 
      run(data) { console.log("Processing 
    ...

    ⭐ Pattern Comparison Table

    PatternWhen to UseAvoid When
    FactoryCreates different objects cleanlyOnly one type exists
    SingletonOnly one object must exist globallyAnything user-specific
    StrategyMany behaviours/algorithmsOnly one behaviour needed
    ObserverMany listeners for one eventStrict order/sequence needed
    DecoratorAdd features without touching codeToo many wrappers
    FacadeSimplify a complex systemNo actual complexity

    ✅ Senior-Level Understanding

    • • Patterns are mental tools, not copy/paste code
    • • Factory: Creates objects without exposing creation logic
    • • Singleton: One instance globally (config, logging, cache)
    • • Strategy: Swap algorithms without rewriting code
    • • Observer: One event, many listeners
    • • Decorator: Add features by wrapping functions
    • • Facade: Hide complexity behind clean APIs
    • • Combine patterns for real-world systems
    • • Use patterns only when they reduce complexity

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous