Creational Patterns

Singleton: One instance globally. Use for database connections, configuration, logging. In JS: export a module-level instance. Caution: singletons make testing harder — prefer dependency injection. Factory: Create objects without specifying exact class. createNotification('email') returns an EmailNotification. Use when object creation logic is complex or varies by type. Builder: Construct complex objects step-by-step. new QueryBuilder().select('name').where('active', true).limit(10).build(). Use when objects have many optional parameters.

Structural Patterns

Adapter: Make incompatible interfaces work together. Wrap a third-party API to match your internal interface. Decorator: Add behavior to objects dynamically. TypeScript decorators, Express middleware, and React HOCs are all decorator patterns. Facade: Simplify complex subsystems behind a simple interface. Your API client that wraps fetch, authentication, error handling, and retry logic is a facade. Proxy: Control access to an object. JavaScript Proxy objects, lazy loading, and caching layers are proxies.

Behavioral Patterns

Observer: Objects subscribe to events and get notified of changes. React's useState, EventEmitter, and pub/sub systems use this pattern. Strategy: Define a family of algorithms, make them interchangeable. Instead of if (type === 'credit')... else if (type === 'paypal'), use paymentStrategies[type].process(). Command: Encapsulate a request as an object. Enables undo/redo, queuing, and logging. Redux actions are commands.

Modern Patterns in 2026

Repository: Abstract data access layer. Switch databases without changing business logic. Middleware: Chain processing steps (Express, Redux). Module: ES modules are the standard — organize code into cohesive, self-contained units. Dependency Injection: Pass dependencies instead of creating them. Makes testing trivial. NestJS and Angular use DI extensively. These modern patterns reflect how we build software today — composable, testable, and decoupled.

Patterns in React

Compound Components: Components that work together implicitly (Tabs, TabList, Tab). Render Props: Pass a function as a child to share logic. Custom Hooks: Extract reusable logic from components. Provider Pattern: React Context for dependency injection. Container/Presentational: Separate data fetching from UI rendering. These React-specific patterns build on classical patterns — custom hooks are essentially the Strategy pattern for component logic.

Anti-Patterns to Avoid

God Object: A class that does everything. Split into focused, single-responsibility modules. Premature Optimization: Don't add patterns before they're needed. Cargo Cult Programming: Using patterns because "best practice" without understanding why. Golden Hammer: Using one pattern for everything. The right pattern depends on the problem — not every problem needs a pattern. Start simple and refactor toward patterns when complexity demands it.

When to Apply Patterns

Apply patterns when you notice: (1) Code duplication across features, (2) Complex conditional logic, (3) Tight coupling between components, (4) Difficulty testing in isolation. Don't apply patterns preventatively. Follow the Rule of Three: wait until you see a pattern repeated three times before abstracting. Review SOLID principles to understand the foundational thinking behind patterns.