💡 Running Code Locally: While this online editor runs real JavaScript, some advanced examples may have limitations. For the best experience:
.html file with <script> tags and open it in your browserMaster Factory, Singleton, Strategy, Observer, Decorator, and Facade patterns for scalable applications
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.
Object creation: Factory, Singleton, Builder, Prototype
Object relationships: Adapter, Facade, Decorator, Proxy
Object behaviour: Strategy, Observer, Command, State
Creates objects without exposing the creation logic. Use when object creation depends on input or you need different classes based on conditions.
Create objects without exposing creation logic
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
Ensures only one instance of a class exists throughout the app. Perfect for configuration, database connections, logging, caching, or global state.
Ensure only one instance exists
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.
Switch between different algorithms without rewriting code. Your anti-if/else superpower for payment methods, sorting, filters, shipping rules, etc.
Switch between different algorithms
// 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
...One event, many listeners. Used in UI frameworks, WebSockets, pub/sub systems, notifications, and data stores.
One event, many listeners
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
...Add features to an object without changing its original code. Perfect for logging, caching, authentication checks, retry logic, and performance measurement.
Add features without changing original code
// 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
...Simplifies complex systems behind a clean API. Hide ugly complexity from users of your code.
Simplify complex systems behind a clean API
// 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) {
...Combining Strategy + Factory + Decorator + Singleton for a professional login system.
Strategy + Factory + Decorator + Singleton combined
// 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
...Turning messy code into clean, extensible architecture.
Turn messy code into clean architecture
// ❌ 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 | When to Use | Avoid When |
|---|---|---|
| Factory | Creates different objects cleanly | Only one type exists |
| Singleton | Only one object must exist globally | Anything user-specific |
| Strategy | Many behaviours/algorithms | Only one behaviour needed |
| Observer | Many listeners for one event | Strict order/sequence needed |
| Decorator | Add features without touching code | Too many wrappers |
| Facade | Simplify a complex system | No actual complexity |
Sign up for free to track which lessons you've completed and get learning reminders.