Lesson 13 • Expert
Design Patterns
Master proven solutions to common programming problems with battle-tested design patterns.
What You'll Learn in This Lesson
- ✓Creational Patterns (Singleton, Factory, Builder)
- ✓Structural Patterns (Module, Adapter, Decorator)
- ✓Behavioral Patterns (Observer, Strategy)
- ✓When to use each pattern
- ✓Real-world implementations in JS
- ✓Pros and cons of each approach
💡 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
.htmlfile with<script>tags and open it in your browser
🏗️ Real-World Analogy: Architectural Blueprints
Think of design patterns like architectural blueprints for houses. Just as architects don't redesign plumbing from scratch for every house (they use proven patterns), software developers use design patterns to solve recurring problems. A "kitchen layout pattern" works whether you're building a cottage or a mansion — similarly, the "Observer pattern" works whether you're building a chat app or a stock ticker.
Patterns aren't code you copy-paste — they're proven strategies you adapt to your specific needs.
📋 Which Pattern Should I Use?
| Problem | Pattern | Real Example |
|---|---|---|
| Need only one instance globally | Singleton | Database connection, Logger |
| Create different objects based on type | Factory | User types (Admin, Guest) |
| Notify multiple objects of changes | Observer | Event listeners, React state |
| Build complex objects step by step | Builder | Query builders, form builders |
| Add features without changing core | Decorator | Middleware, HOCs in React |
What Are Design Patterns?
Design patterns are reusable, battle-tested solutions to common programming problems. They are not specific pieces of code you must copy, but structured ideas you can implement in many ways using JavaScript.
You can think of them like:
- Blueprints for solving common design problems
- Templates for structuring code in a maintainable way
- Best practices discovered by many developers over decades
In this expert-level lesson, you'll learn:
- Why design patterns matter for real projects (apps, games, SaaS)
- The main categories of patterns
- Core creational, structural, and behavioral patterns
- How to implement them using modern ES6+ features
- Real-world use cases across web apps, games, and systems
1. Creational Patterns — How to Build Objects
Creational patterns deal with object creation mechanisms, trying to create objects in a manner suitable to the situation.
Singleton
Ensures only one instance of a class exists.
Example
class Logger {
constructor() {
if (Logger.instance == null) {
Logger.instance = this;
this.logs = [];
}
return Logger.instance;
}
log(message) {
this.logs.push(message);
console.log(`Logger: ${message}`);
}
}
const logger1 = new Logger();
const logger2 = new Logger();
logger1.log("First log");
logger2.log("Second log");
console.log(logger1 === logger2); // true
Factory
Creates objects without specifying the exact class to create.
Example
class Car {
constructor(model) {
this.model = model;
}
}
class CarFactory {
create(model) {
return new Car(model);
}
}
const factory = new CarFactory();
const myCar = factory.create("Tesla");
console.log(myCar.model);
Builder
Separates the construction of a complex object from its representation.
Example
class QueryBuilder {
constructor() {
this.query = {
select: [],
from: null,
where: []
};
}
select(fields) {
this.query.select = fields;
return this;
}
from(table) {
this.query.from = table;
return this;
}
where(condition) {
this.query.where.push(condition);
return this;
}
build() {
return this.query;
}
}
const query = new QueryBuilder()
.se
...2. Structural Patterns — How to Compose Objects
Structural patterns explain how to assemble objects to form larger structures, keeping these structures flexible and efficient.
Module
Encapsulates a part of an application into a single unit.
Example
const calculator = (() => {
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
return {
add: add,
subtract: subtract
};
})();
console.log(calculator.add(5, 3));
console.log(calculator.subtract(5, 3));
Decorator
Dynamically adds responsibilities to an object.
Example
class Coffee {
getCost() {
return 5;
}
getDescription() {
return "Simple coffee";
}
}
class MilkDecorator {
constructor(coffee) {
this.coffee = coffee;
}
getCost() {
return this.coffee.getCost() + 2;
}
getDescription() {
return this.coffee.getDescription() + ", milk";
}
}
const coffee = new Coffee();
const milkCoffee = new MilkDecorator(coffee);
console.log(milkCoffee.getCost());
console.log(milkCoffee.getDesc
...Facade
Provides a simplified interface to a complex subsystem.
Example
class CPU {
freeze() { return "CPU Freeze"; }
jump(position) { return "CPU Jump"; }
execute() { return "CPU Execute"; }
}
class Memory {
load(position) { return "Memory Load"; }
}
class HardDrive {
read(lba, size) { return "HardDrive Read"; }
}
class ComputerFacade {
constructor() {
this.cpu = new CPU();
this.memory = new Memory();
this.hardDrive = new HardDrive();
}
start() {
this.cpu.freeze();
this.memory.load("0x00")
...3. Behavioral Patterns — How Objects Interact
Behavioral patterns are concerned with algorithms and the assignment of responsibilities between objects.
Observer
Defines a one-to-many dependency between objects.
Example
class Subject {
constructor() {
this.observers = [];
}
subscribe(observer) {
this.observers.push(observer);
}
unsubscribe(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
}
notify(data) {
this.observers.forEach(observer => observer.update(data));
}
}
class Observer {
update(data) {
console.log(`Observer received data: ${data}`);
}
}
const subject = new Subject();
const observer1 = ne
...Strategy
Defines a family of algorithms, encapsulates each one, and makes them interchangeable.
Example
class Sorter {
constructor(strategy) {
this.strategy = strategy;
}
setStrategy(strategy) {
this.strategy = strategy;
}
sort(data) {
return this.strategy.sort(data);
}
}
class BubbleSortStrategy {
sort(data) {
console.log("Bubble sort");
return data.sort();
}
}
class QuickSortStrategy {
sort(data) {
console.log("Quick sort");
return data.sort();
}
}
const data = [3, 1, 4, 1, 5, 9, 2, 6];
const s
...What You've Mastered
You now have expert-level understanding of JavaScript design patterns:
- ✔ Creational Patterns – Singleton, Factory, Builder
- ✔ Structural Patterns – Module, Decorator, Facade, Proxy, Adapter
- ✔ Behavioral Patterns – Observer, Strategy, State, Command, Mediator
- ✔ Real-world applications across web apps, games, and complex systems
- ✔ Modern ES6+ implementations with classes, private fields, and modules
- ✔ When to use each pattern and avoid common pitfalls
These patterns are the foundation of professional JavaScript development. They're used in every major framework, game engine, and large-scale application. Master them, and you'll write cleaner, more maintainable, and more scalable code.
📋 Quick Reference — Design Patterns
| Pattern | Best For |
|---|---|
| Singleton | Global state (DB, Logger) |
| Factory | Complex object creation |
| Observer | Event handling & subscriptions |
| Module | Encapsulation & privacy |
| Decorator | Extending functionality |
Lesson 13 Complete — Design Patterns!
You now have a toolbox of proven architectural solutions. You don't just write code; you design systems.
Up next: Performance Optimization — making your apps lightning fast! 🚀
Sign up for free to track which lessons you've completed and get learning reminders.