跳到主要内容

Design Patterns

Design patterns = proven solutions to common problems


What are Design Patterns?

"Reusable solutions to recurring problems"

Design patterns are:

  • Proven solutions to common problems
  • Reusable templates
  • Language-agnostic concepts
  • Best practices in software design

"Design patterns are reusable solutions to common software design problems that provide proven approaches to structuring code."


Categories of Patterns

Creational · Structural · Behavioral

CategoryPurposeExamples
CreationalObject creationSingleton, Factory
StructuralObject compositionAdapter, Decorator
BehavioralObject interactionObserver, Strategy

Singleton Pattern

One instance only

class Singleton {
static instance;
static getInstance() {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
}

Use when: Need single instance (config, logger)

"Singleton ensures only one instance of a class exists, useful for shared resources."


Factory Pattern

Create objects without specifying exact class

class ButtonFactory {
createButton(type) {
if (type === "primary") return new PrimaryButton();
if (type === "secondary") return new SecondaryButton();
}
}

Use when: Object creation logic is complex

"Factory pattern encapsulates object creation, providing a way to create objects without specifying their exact classes."


Observer Pattern

Subscribe and notify

class Subject {
observers = [];
subscribe(observer) {
this.observers.push(observer);
}
notify(data) {
this.observers.forEach((o) => o.update(data));
}
}

Use when: Need to notify multiple objects of changes

"Observer pattern defines a one-to-many dependency where observers are notified of state changes."


Module Pattern

Encapsulate private/public

const Module = (function () {
let private = "hidden";
return {
public: "visible",
getPrivate: () => private,
};
})();

Use when: Need to encapsulate code and create namespaces

"Module pattern uses closures to create private and public members, providing encapsulation."


Strategy Pattern

Interchangeable algorithms

class PaymentProcessor {
constructor(strategy) {
this.strategy = strategy;
}
process(amount) {
return this.strategy.pay(amount);
}
}

Use when: Multiple ways to perform a task

"Strategy pattern defines a family of algorithms and makes them interchangeable."


Adapter Pattern

Bridge incompatible interfaces

class OldAPI {
oldMethod() {
return "data";
}
}

class Adapter {
constructor(oldAPI) {
this.api = oldAPI;
}
newMethod() {
return this.api.oldMethod();
}
}

Use when: Need to use incompatible interfaces together

"Adapter pattern allows incompatible interfaces to work together by wrapping one interface with another."


9️⃣ Decorator Pattern

Add behavior dynamically

class Coffee {
cost() {
return 5;
}
}

class MilkDecorator {
constructor(coffee) {
this.coffee = coffee;
}
cost() {
return this.coffee.cost() + 2;
}
}

Use when: Need to add responsibilities to objects dynamically

"Decorator pattern adds behavior to objects dynamically without altering their structure."


React-Specific Patterns

HOC · Render Props · Hooks

  • HOC (Higher-Order Component): Component wrapper
  • Render Props: Function as prop
  • Custom Hooks: Reusable logic
  • Compound Components: Related components together

"React uses patterns like HOCs, render props, and custom hooks for code reuse and composition."


"Design patterns are reusable solutions to common problems. Creational patterns handle object creation (Singleton, Factory), structural patterns organize objects (Adapter, Decorator), and behavioral patterns manage object communication (Observer, Strategy). In front-end development, patterns like Module, Observer, and React-specific patterns (HOCs, hooks) are commonly used."


🧠 Ultra-Short Cheat Sheet

Creational (Singleton, Factory)
Structural (Adapter, Decorator)
Behavioral (Observer, Strategy)
Module pattern
React patterns (HOC, Hooks)
Reusable solutions