Starphix
Software Engineering / Sources
The Lab / Sources / Software Engineering / Patterns/Design-Patterns.md

Design Patterns

Recurring solutions to common software design problems. Use as vocabulary, not as checklist.


Creational Patterns

Pattern Purpose When to Use
Factory Method Delegate instantiation to subclasses Class can't anticipate subclass; delegate creation
Abstract Factory Families of related objects without concrete classes Multiple product families; enforce consistency
Builder Construct complex objects step by step Many optional parameters; immutable objects
Prototype Clone existing objects Creation expensive; similar objects with variations
Singleton Ensure single instance; global access Rarely — prefer dependency injection; testability issues

Structural Patterns

Pattern Purpose When to Use
Adapter Make incompatible interfaces work together Legacy code; third-party libs; interface mismatch
Bridge Decouple abstraction from implementation Both vary independently; avoid permanent binding
Composite Tree structures of objects (part-whole) Hierarchies; uniform treatment of leaf/composite
Decorator Add behavior dynamically Open/Closed; alternative to subclassing
Facade Simplified interface to complex subsystem Reduce coupling; provide simple entry point
Flyweight Share fine-grained objects efficiently Many similar objects; memory constrained
Proxy Placeholder controlling access Lazy loading; access control; logging; remote

Behavioral Patterns

Pattern Purpose When to Use
Chain of Responsibility Pass request along handler chain Multiple handlers; dynamic dispatch
Command Encapsulate request as object Undo/redo; queue requests; macro commands
Interpreter Define grammar + interpreter DSLs; rule engines; simple languages
Iterator Sequential access without exposing structure Aggregate objects; multiple traversals
Mediator Centralize communication between objects Reduce coupling; complex interactions
Memento Capture/restore object state Undo; snapshots; checkpoints
Observer Publish/subscribe notifications Event-driven; loose coupling
State Alter behavior when internal state changes Complex state-dependent behavior
Strategy Encapsulate interchangeable algorithms Algorithm varies; runtime selection
Template Method Define skeleton; defer steps to subclasses Common algorithm structure; variant steps
Visitor Add operations without modifying classes Stable object structure; varying operations

Enterprise Patterns (Martin Fowler)

Domain Logic

Pattern Description
Transaction Script Single procedure per use case; simple but doesn't scale
Domain Model Rich objects with behavior + data; complex domains
Table Module One class per DB table; business logic in class
Service Layer Defines application boundary; coordinates transactions

Data Source

Pattern Description
Active Record Domain object wraps DB row + access
Data Mapper Separates domain from DB; mapper in between
Repository Collection-like interface for aggregates (DDD)
Unit of Work Tracks changes; writes in single transaction

Object-Relational

Pattern Description
Identity Map Ensures each DB row loaded once per session
Lazy Load Defer loading until accessed
Metadata Mapping ORM config via annotations/XML

Web Presentation

Pattern Description
MVC Model-View-Controller separation
Page Controller One controller per page/action
Front Controller Single entry point dispatches to handlers
Template View HTML with embedded markers

Distribution

Pattern Description
Remote Facade Coarse-grained interface for remote access
Data Transfer Object Serializable data carrier for remote calls

Concurrency

Pattern Description
Optimistic Lock Version field; retry on conflict
Pessimistic Lock DB lock; blocks others

Session State

Pattern Description
Client Session State Store in client (cookie, localStorage)
Server Session State Store in server memory/DB
Database Session State Store in DB

Anti-Patterns (Avoid)

Anti-Pattern Description Better Approach
God Object One class does everything Decompose by responsibility
Anemic Domain Model Data bags + separate services Rich domain model (DDD)
Spaghetti Code No structure; tangled dependencies Layered/hexagonal architecture
Copy-Paste Programming Duplicate code instead of abstraction Extract common; DRY (knowledge)
Golden Hammer Favorite pattern used everywhere Right tool for the job
Premature Optimization Complex code for unmeasured gains Measure first; optimize bottlenecks
YAGNI Violation Building for imaginary futures Build for current requirements
Pattern Overload Patterns for pattern's sake Solve the problem simply

Pattern Selection Guide

Problem Consider
Need to create objects flexibly Factory, Builder, Prototype
Need to compose objects Composite, Decorator
Need to simplify interface Facade, Adapter
Need to change behavior dynamically Strategy, State, Decorator
Need to decouple sender/receiver Command, Observer, Mediator
Need to traverse structures Iterator, Visitor
Need to manage algorithm variations Strategy, Template Method
Need to handle cross-cutting concerns Decorator, Proxy, Aspect

Modern Pattern Evolution

Functional Alternatives

OO Pattern Functional Equivalent
Strategy Higher-order functions
Decorator Function composition
Observer Event streams (RxJS, Reactor)
Command Data + pure functions
Visitor Pattern matching / ADTs

Cloud-Native Patterns

Pattern Purpose
Circuit Breaker Fail fast; prevent cascade failures
Bulkhead Isolate resources; limit blast radius
Retry with Backoff Transient fault handling
Timeout Bound wait time
Rate Limiter Protect downstream
Cache-Aside Read performance
Event Sourcing Audit trail; temporal queries
CQRS Separate read/write models
Saga Distributed transactions
Sidecar Cross-cutting concerns in separate process

Using Patterns Wisely

  1. Learn the names — Shared vocabulary for design discussions
  2. Recognize the problem — Pattern matches problem, not reverse
  3. Apply judiciously — Simplicity > pattern conformance
  4. Compose patterns — Real systems combine many
  5. Know anti-patterns — Diagnostic labels for code smells

"Patterns are useful shared names for recurring solutions. Reach for one when the problem actually matches it. Don't impose patterns to look sophisticated — pattern-heavy code is often a sign of over-engineering."


  • Design Principles — Principles underlying patterns
  • Architectural Styles — Patterns at architecture level
  • Integration Patterns — Communication patterns
  • Resilience Patterns — Fault tolerance patterns
  • Concurrency Patterns — Threading/async patterns
  • Domain Driven Design — DDD tactical patterns

Sources: Design Patterns (GoF), Patterns of Enterprise Application Architecture (Fowler), Cloud Design Patterns (Microsoft/AWS), Software Engineering Guide, SourceMaking, Refactoring.Guru

From the Software Engineering research vault · CC BY 4.0 · all notes · raw markdown