Essential Software Design Patterns: Architectural Principles and Multi-Language Implementations
Design patterns offer proven, language-agnostic blueprints for solving recurring software engineering challenges. While the underlying architectural principles remain universal, their concrete implementations vary meaningfully depending on each language’s type system, memory model, and native language features.
Here is a practical, code-first guide to ten essential design patterns—beginning with Singleton, Flyweight, Observer, and Registry—featuring side-by-side implementations in Python, Java, and C++.
Quick Reference: Pattern Classification
| Pattern | Category | Primary Intent | Language-Specific Idioms |
|---|---|---|---|
| Singleton | Creational | Guarantee a single global instance of a class | Python: Metaclass / Module Java: Bill Pugh Holder idiom / enumC++: Meyers’ Singleton ( static local) |
| Flyweight | Structural | Drastically cut memory usage by sharing immutable intrinsic state | Python: Factory + __slots__Java: record + ConcurrentHashMapC++: std::shared_ptr<const T> pool |
| Observer | Behavioral | Decoupled one-to-many publish-subscribe event notification | Python: Listener lists / callables Java: @FunctionalInterface + CopyOnWriteArrayListC++: std::vector<std::weak_ptr<Observer>> |
| Registry | Creational | Centralized catalog mapping string keys to constructors/factories | Python: Decorator / __init_subclass__Java: Map<String, Supplier<T>>C++: Static map of factory lambdas |
| Factory Method | Creational | Delegate object instantiation without binding to concrete classes | Python: Dynamic callable dispatch Java: Interface + switch expressions C++: std::unique_ptr<Base> return |
| Builder | Creational | Construct complex multi-attribute objects step-by-step | Python / Java / C++: Method chaining / Fluent API |
| Adapter | Structural | Convert incompatible interfaces to match what client expects | Python / Java / C++: Wrapper composition / delegation |
| Decorator | Structural | Attach behavior to objects dynamically at runtime without subclassing | Python / Java / C++: Wrapper composition matching base interface |
| Strategy | Behavioral | Encapsulate interchangeable algorithms selected at runtime | Python / Java: First-class functions / @FunctionalInterface lambdasC++: std::function or strategy class |
| Chain of Responsibility | Behavioral | Pass requests sequentially through a pipeline of handlers | Python / Java / C++: Linked handler list / middleware pipeline |
1. The Singleton Pattern (Creational)
Core Concept & Intent
The Singleton Pattern ensures that a class has only one instance while providing a global access point to it. It is commonly employed for connection pools, logging managers, thread pools, and hardware controllers.
Structural Architecture
┌──────────────────────────────────────┐
│ Singleton Class │
├──────────────────────────────────────┤
│ - static instance: Singleton │
│ - constructor() [Private / Hidden] │
├──────────────────────────────────────┤
│ + static getInstance(): Singleton │
│ + executeOperation(): void │
└──────────────────────────────────────┘
Multi-Language Implementations
Python (Thread-Safe Metaclass)
import threading
from typing import Any, Dict
class SingletonMeta(type):
"""Thread-safe Singleton metaclass using double-checked locking."""
_instances: Dict[type, Any] = {}
_lock: threading.Lock = threading.Lock()
def __call__(cls, *args: Any, **kwargs: Any) -> Any:
if cls not in cls._instances:
with cls._lock:
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class DatabasePool(metaclass=SingletonMeta):
def __init__(self, dsn: str = "postgresql://localhost:5432/app") -> None:
self.dsn = dsn
def query(self, sql: str) -> str:
return f"Querying '{sql}' on {self.dsn}"
# Usage
db1 = DatabasePool()
db2 = DatabasePool()
assert db1 is db2 # Exactly the same instance in memory
Java (Bill Pugh Singleton / Initialization-on-Demand Holder)
public class DatabasePool {
private final String dsn;
// Private constructor prevents direct instantiation
private DatabasePool() {
this.dsn = "postgresql://localhost:5432/app";
}
// Bill Pugh idiom: Thread-safe, lazily initialized on first access without synchronization overhead
private static class Holder {
private static final DatabasePool INSTANCE = new DatabasePool();
}
public static DatabasePool getInstance() {
return Holder.INSTANCE;
}
public String query(String sql) {
return "Querying '" + sql + "' on " + dsn;
}
}
// Usage
DatabasePool db1 = DatabasePool.getInstance();
DatabasePool db2 = DatabasePool.getInstance();
System.out.println(db1 == db2); // true (identical reference)
C++ (Meyers’ Singleton)
#include <iostream>
#include <string>
class DatabasePool {
public:
// Delete copy and move semantics to enforce single instance
DatabasePool(const DatabasePool&) = delete;
DatabasePool& operator=(const DatabasePool&) = delete;
DatabasePool(DatabasePool&&) = delete;
DatabasePool& operator=(DatabasePool&&) = delete;
// Thread-safe in C++11 and later (static local initialization is atomic)
static DatabasePool& getInstance() {
static DatabasePool instance("postgresql://localhost:5432/app");
return instance;
}
void query(const std::string& sql) const {
std::cout << "Executing '" << sql << "' on " << dsn_ << "\n";
}
private:
explicit DatabasePool(std::string dsn) : dsn_(std::move(dsn)) {}
std::string dsn_;
};
// Usage
int main() {
DatabasePool& db1 = DatabasePool::getInstance();
DatabasePool& db2 = DatabasePool::getInstance();
// &db1 == &db2 (Identical memory address)
return 0;
}
2. The Flyweight Pattern (Structural)
Core Concept & Intent
The Flyweight Pattern reduces memory footprint by sharing common, immutable state across thousands or millions of fine-grained objects. State is separated into:
- Intrinsic State: Context-independent, immutable data stored inside the shared Flyweight (e.g., symbol, exchange, currency).
- Extrinsic State: Context-dependent, mutable data passed in from the client (e.g., order ID, timestamp, volume, execution price).
Structural Architecture
┌─────────────────────────────────┐
│ FlyweightFactory │ ◄── Caches & shares unique flyweights
├─────────────────────────────────┤
│ - cache: map<key, Flyweight> │
├─────────────────────────────────┤
│ + get(symbol, exchange): FW │
└────────────────▲────────────────┘
│ references
┌────────────────┴────────────────┐ ┌───────────────────────────────┐
│ Flyweight (Metadata) │ │ Context (Order) │
├─────────────────────────────────┤ ├───────────────────────────────┤
│ + symbol: string (Intrinsic) │◄──────┼─+ security: Flyweight │
│ + exchange: string (Intrinsic) │ │ + orderId: int (Extrinsic) │
│ + currency: string (Intrinsic) │ │ + price: float (Extrinsic) │
└─────────────────────────────────┘ └───────────────────────────────┘
Multi-Language Implementations
Python
from dataclasses import dataclass
from typing import Dict, Tuple
@dataclass(frozen=True, slots=True)
class SecurityMetadata:
"""Intrinsic State: Immutable and shared across millions of orders."""
symbol: str
exchange: str
currency: str
class SecurityFlyweightFactory:
"""Factory managing the pool of unique Flyweight instances."""
_pool: Dict[Tuple[str, str], SecurityMetadata] = {}
@classmethod
def get(cls, symbol: str, exchange: str, currency: str) -> SecurityMetadata:
key = (symbol.upper(), exchange.upper())
if key not in cls._pool:
cls._pool[key] = SecurityMetadata(
symbol=symbol.upper(),
exchange=exchange.upper(),
currency=currency.upper(),
)
return cls._pool[key]
class Order:
"""Extrinsic Context: Stores specific transaction state + Flyweight pointer."""
__slots__ = ("order_id", "security", "price", "shares")
def __init__(
self,
order_id: int,
security: SecurityMetadata,
price: float,
shares: int,
) -> None:
self.order_id = order_id
self.security = security # Pointer to shared Flyweight
self.price = price
self.shares = shares
# Usage: 100,000 orders share exactly ONE metadata object
aapl_meta = SecurityFlyweightFactory.get("AAPL", "NASDAQ", "USD")
orders = [
Order(order_id=i, security=aapl_meta, price=180.0, shares=50)
for i in range(100_000)
]
assert orders[0].security is orders[99999].security
Java (Immutable Record + ConcurrentHashMap)
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
// Flyweight: Immutable record holding intrinsic state
public record SecurityMetadata(String symbol, String exchange, String currency) {}
public class SecurityFlyweightFactory {
private static final Map<String, SecurityMetadata> POOL = new ConcurrentHashMap<>();
public static SecurityMetadata get(String symbol, String exchange, String currency) {
String key = (symbol + ":" + exchange).toUpperCase();
return POOL.computeIfAbsent(key, k -> new SecurityMetadata(
symbol.toUpperCase(), exchange.toUpperCase(), currency.toUpperCase()
));
}
}
public class Order {
private final int orderId;
private final SecurityMetadata security; // Pointer to shared Flyweight
private double price;
private int quantity;
public Order(int orderId, SecurityMetadata security, double price, int quantity) {
this.orderId = orderId;
this.security = security;
this.price = price;
this.quantity = quantity;
}
public SecurityMetadata getSecurity() { return security; }
}
// Usage: 100,000 orders share exactly ONE metadata record in heap
SecurityMetadata meta = SecurityFlyweightFactory.get("AAPL", "NASDAQ", "USD");
Order o1 = new Order(1, meta, 185.5, 100);
Order o2 = new Order(2, meta, 186.0, 200);
System.out.println(o1.getSecurity() == o2.getSecurity()); // true (same reference)
C++
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
struct SecurityMetadata {
const std::string symbol;
const std::string exchange;
const std::string currency;
};
class SecurityFlyweightFactory {
public:
static std::shared_ptr<const SecurityMetadata> get(const std::string& symbol, const std::string& exchange, const std::string& currency) {
std::string key = symbol + ":" + exchange;
auto it = pool_.find(key);
if (it == pool_.end()) {
auto meta = std::make_shared<const SecurityMetadata>(SecurityMetadata{symbol, exchange, currency});
pool_[key] = meta;
return meta;
}
return it->second;
}
private:
static inline std::unordered_map<std::string, std::shared_ptr<const SecurityMetadata>> pool_;
};
struct Order {
int orderId;
std::shared_ptr<const SecurityMetadata> security; // Shared pointer to flyweight
double price;
int quantity;
};
3. The Observer Pattern (Behavioral)
Core Concept & Intent
The Observer Pattern defines a one-to-many relationship where a core subject (publisher) automatically broadcasts state changes or events to an arbitrary list of registered observers (subscribers) without knowing their concrete types.
Structural Architecture
┌──────────────────────────────────────┐
│ Subject (Feed) │
├──────────────────────────────────────┤
│ - observers: List<Observer> │
├──────────────────────────────────────┤
│ + subscribe(observer: Observer) │
│ + unsubscribe(observer: Observer) │
│ + notify(data: EventData) │
└──────────────────▲───────────────────┘
│ broadcasts to
┌─────────┴─────────┐
│ │
┌────────┴────────┐ ┌────────┴────────┐
│ TradingStrategy │ │ RiskMonitor │ (Observers)
└─────────────────┘ └─────────────────┘
Multi-Language Implementations
Python
from abc import ABC, abstractmethod
from typing import Any, Dict, List
class Observer(ABC):
@abstractmethod
def on_event(self, event_type: str, data: Dict[str, Any]) -> None:
pass
class MarketFeed:
def __init__(self) -> None:
self._subscribers: List[Observer] = []
def subscribe(self, observer: Observer) -> None:
if observer not in self._subscribers:
self._subscribers.append(observer)
def unsubscribe(self, observer: Observer) -> None:
self._subscribers.remove(observer)
def emit(self, event_type: str, data: Dict[str, Any]) -> None:
for sub in self._subscribers:
sub.on_event(event_type, data)
class TradeDesk(Observer):
def on_event(self, event_type: str, data: Dict[str, Any]) -> None:
print(f"[Desk] Received {event_type}: {data}")
# Usage
feed = MarketFeed()
desk = TradeDesk()
feed.subscribe(desk)
feed.emit("PRICE_TICK", {"ticker": "NVDA", "price": 142.50})
Java (Thread-Safe Functional Interface + CopyOnWriteArrayList)
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@FunctionalInterface
public interface MarketObserver {
void onTick(String symbol, double price);
}
public class MarketFeed {
// Thread-safe list permitting safe concurrent iterations during event emission
private final List<MarketObserver> listeners = new CopyOnWriteArrayList<>();
public void subscribe(MarketObserver listener) {
listeners.add(listener);
}
public void unsubscribe(MarketObserver listener) {
listeners.remove(listener);
}
public void emit(String symbol, double price) {
for (MarketObserver listener : listeners) {
listener.onTick(symbol, price);
}
}
}
// Usage with Lambdas / Method References
MarketFeed feed = new MarketFeed();
feed.subscribe((sym, price) -> System.out.println("[Desk 1] " + sym + " traded at $" + price));
feed.subscribe((sym, price) -> System.out.println("[Risk Engine] Auditing tick for " + sym));
feed.emit("NVDA", 142.50);
C++
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
class Observer {
public:
virtual ~Observer() = default;
virtual void onEvent(const std::string& eventType, double value) = 0;
};
class MarketFeed {
public:
void subscribe(std::shared_ptr<Observer> obs) {
subscribers_.push_back(obs);
}
void emit(const std::string& eventType, double value) {
for (auto& sub : subscribers_) {
sub->onEvent(eventType, value);
}
}
private:
std::vector<std::shared_ptr<Observer>> subscribers_;
};
class DisplayDashboard : public Observer {
public:
void onEvent(const std::string& eventType, double value) override {
std::cout << "[Dashboard] " << eventType << ": " << value << "\n";
}
};
4. The Registry Pattern (Creational / Architectural)
Core Concept & Intent
The Registry Pattern provides a centralized, decoupled catalog where components or plugins register themselves under unique keys. Callers instantiate or look up components dynamically without hardcoding if/elif ladders or switch statements.
It is heavily used in frameworks like Spring (bean registry), PyTorch (model registry), and FastAPI (router registry).
Structural Architecture
┌──────────────────────────────────────────────┐
│ Registry │
├──────────────────────────────────────────────┤
│ - table: map<string, FactoryFunction> │
├──────────────────────────────────────────────┤
│ + register(key: string, factory: Factory) │
│ + create(key: string, ...args): Product │
└───────────────────────▲──────────────────────┘
│ self-registers
┌───────────────┴───────────────┐
┌───────┴─────────┐ ┌─────────┴─────────┐
│ JsonProcessor │ │ CsvProcessor │
└─────────────────┘ └───────────────────┘
Multi-Language Implementations
Python (Decorator-Driven Registry)
from typing import Any, Callable, Dict, Type
class ParserRegistry:
_catalog: Dict[str, Type["BaseParser"]] = {}
@classmethod
def register(cls, key: str) -> Callable[[Type["BaseParser"]], Type["BaseParser"]]:
"""Class decorator for self-registering parser subclasses."""
def decorator(subclass: Type["BaseParser"]) -> Type["BaseParser"]:
cls._catalog[key.lower()] = subclass
return subclass
return decorator
@classmethod
def create(cls, key: str, *args: Any, **kwargs: Any) -> "BaseParser":
parser_cls = cls._catalog.get(key.lower())
if not parser_cls:
available = ", ".join(cls._catalog.keys())
raise KeyError(f"Unknown parser: '{key}'. Available: [{available}]")
return parser_cls(*args, **kwargs)
class BaseParser:
def parse(self, text: str) -> str:
raise NotImplementedError
@ParserRegistry.register("json")
class JsonParser(BaseParser):
def parse(self, text: str) -> str:
return f"Parsed JSON data: '{text}'"
@ParserRegistry.register("csv")
class CsvParser(BaseParser):
def parse(self, text: str) -> str:
return f"Parsed CSV rows: '{text}'"
# Dynamic factory instantiation
parser = ParserRegistry.create("json")
Java (Concurrent Map of Suppliers)
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
public interface DocumentParser {
String parse(String raw);
}
public class ParserRegistry {
private static final Map<String, Supplier<DocumentParser>> REGISTRY = new ConcurrentHashMap<>();
public static void register(String key, Supplier<DocumentParser> supplier) {
REGISTRY.put(key.toLowerCase(), supplier);
}
public static DocumentParser create(String key) {
Supplier<DocumentParser> supplier = REGISTRY.get(key.toLowerCase());
if (supplier == null) {
throw new IllegalArgumentException("Unknown parser: " + key);
}
return supplier.get();
}
}
// Concrete implementation
public class JsonParser implements DocumentParser {
@Override
public String parse(String raw) { return "Parsed JSON: " + raw; }
}
// Self-registration via static initializer or application bootstrap
// ParserRegistry.register("json", JsonParser::new);
// DocumentParser parser = ParserRegistry.create("json");
C++ (Self-Registering Factory Map)
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <functional>
class Parser {
public:
virtual ~Parser() = default;
virtual void parse(const std::string& input) = 0;
};
class ParserRegistry {
public:
using FactoryFunc = std::function<std::unique_ptr<Parser>()>;
static void registerParser(const std::string& key, FactoryFunc factory) {
registry_[key] = std::move(factory);
}
static std::unique_ptr<Parser> create(const std::string& key) {
auto it = registry_.find(key);
if (it != registry_.end()) {
return it->second();
}
return nullptr;
}
private:
static inline std::unordered_map<std::string, FactoryFunc> registry_;
};
class XmlParser : public Parser {
public:
void parse(const std::string& input) override {
std::cout << "Parsing XML: " << input << "\n";
}
};
// Global static registration
static const bool xmlRegistered = []() {
ParserRegistry::registerParser("xml", []() { return std::make_unique<XmlParser>(); });
return true;
}();
5. The Factory Method Pattern (Creational)
Core Concept & Intent
The Factory Method Pattern delegates object creation to specialized factory methods or subclasses without coupling client code to concrete classes.
Multi-Language Implementations
Python
from abc import ABC, abstractmethod
class PaymentProcessor(ABC):
@abstractmethod
def pay(self, amount: float) -> str:
pass
class StripeProcessor(PaymentProcessor):
def pay(self, amount: float) -> str:
return f"Paid ${amount:.2f} via Stripe"
class PayPalProcessor(PaymentProcessor):
def pay(self, amount: float) -> str:
return f"Paid ${amount:.2f} via PayPal"
class PaymentFactory:
@staticmethod
def get_processor(method: str) -> PaymentProcessor:
processors = {"stripe": StripeProcessor, "paypal": PayPalProcessor}
cls = processors.get(method.lower())
if not cls:
raise ValueError(f"Unknown payment method: {method}")
return cls()
Java (Polymorphic Interface + Pattern Matching Switch)
public interface PaymentProcessor {
String pay(double amount);
}
public class StripeProcessor implements PaymentProcessor {
@Override
public String pay(double amount) {
return "Paid $" + amount + " via Stripe API";
}
}
public class PayPalProcessor implements PaymentProcessor {
@Override
public String pay(double amount) {
return "Paid $" + amount + " via PayPal Checkout";
}
}
public class PaymentFactory {
public static PaymentProcessor getProcessor(String type) {
return switch (type.toLowerCase()) {
case "stripe" -> new StripeProcessor();
case "paypal" -> new PayPalProcessor();
default -> throw new IllegalArgumentException("Unsupported payment type: " + type);
};
}
}
C++
#include <iostream>
#include <memory>
#include <string>
class PaymentProcessor {
public:
virtual ~PaymentProcessor() = default;
virtual void pay(double amount) = 0;
};
class StripeProcessor : public PaymentProcessor {
public:
void pay(double amount) override {
std::cout << "Paid $" << amount << " via Stripe\n";
}
};
class PaymentFactory {
public:
static std::unique_ptr<PaymentProcessor> getProcessor(const std::string& type) {
if (type == "stripe") return std::make_unique<StripeProcessor>();
return nullptr;
}
};
6. The Builder Pattern (Creational)
Core Concept & Intent
The Builder Pattern constructs complex multi-attribute objects step-by-step through a fluent interface, avoiding bloated telescoping constructors.
Multi-Language Implementations
Python
from typing import List, Optional
class Query:
def __init__(
self,
table: str,
columns: List[str],
filters: List[str],
limit: Optional[int],
) -> None:
self.table = table
self.columns = columns
self.filters = filters
self.limit = limit
def to_sql(self) -> str:
cols = ", ".join(self.columns) if self.columns else "*"
sql = f"SELECT {cols} FROM {self.table}"
if self.filters:
sql += f" WHERE {' AND '.join(self.filters)}"
if self.limit is not None:
sql += f" LIMIT {self.limit}"
return f"{sql};"
class QueryBuilder:
def __init__(self, table: str) -> None:
self._table = table
self._columns: List[str] = []
self._filters: List[str] = []
self._limit: Optional[int] = None
def select(self, *columns: str) -> "QueryBuilder":
self._columns.extend(columns)
return self
def where(self, condition: str) -> "QueryBuilder":
self._filters.append(condition)
return self
def limit(self, count: int) -> "QueryBuilder":
self._limit = count
return self
def build(self) -> Query:
return Query(
table=self._table,
columns=self._columns,
filters=self._filters,
limit=self._limit,
)
# Usage: Multi-line fluent method chaining
sql = (
QueryBuilder("users")
.select("id", "username", "email")
.where("status = 'ACTIVE'")
.where("created_at > '2026-01-01'")
.limit(20)
.build()
.to_sql()
)
Java (Static Inner Builder - Effective Java)
import java.util.List;
public class DatabaseQuery {
private final String table;
private final List<String> columns;
private final Integer limit;
private DatabaseQuery(Builder builder) {
this.table = builder.table;
this.columns = builder.columns;
this.limit = builder.limit;
}
public String toSql() {
String cols = (columns == null || columns.isEmpty()) ? "*" : String.join(", ", columns);
String sql = "SELECT " + cols + " FROM " + table;
if (limit != null) sql += " LIMIT " + limit;
return sql + ";";
}
public static class Builder {
private final String table;
private List<String> columns;
private Integer limit;
public Builder(String table) { this.table = table; }
public Builder select(String... cols) {
this.columns = List.of(cols);
return this;
}
public Builder limit(int limit) {
this.limit = limit;
return this;
}
public DatabaseQuery build() {
return new DatabaseQuery(this);
}
}
}
// Usage
String sql = new DatabaseQuery.Builder("orders")
.select("order_id", "total_amount")
.limit(25)
.build()
.toSql();
C++
#include <iostream>
#include <string>
#include <vector>
class HttpRequest {
public:
std::string url;
std::string method;
int timeoutMs;
};
class HttpRequestBuilder {
public:
explicit HttpRequestBuilder(std::string url) {
request_.url = std::move(url);
request_.method = "GET";
request_.timeoutMs = 5000;
}
HttpRequestBuilder& setMethod(std::string method) {
request_.method = std::move(method);
return *this;
}
HttpRequestBuilder& setTimeout(int ms) {
request_.timeoutMs = ms;
return *this;
}
HttpRequest build() {
return std::move(request_);
}
private:
HttpRequest request_;
};
7. The Adapter Pattern (Structural)
Core Concept & Intent
The Adapter Pattern translates the interface of an existing, legacy, or third-party class into an expected target interface without modifying the original source code.
Multi-Language Implementations
Python
from abc import ABC, abstractmethod
import xml.etree.ElementTree as ET
class LegacyXmlService:
"""Adaptee: Third-party service returning raw XML."""
def get_xml(self) -> str:
return "<data><price>150.25</price></data>"
class PriceTarget(ABC):
"""Target interface expected by client code."""
@abstractmethod
def get_price(self) -> float:
pass
class XmlPriceAdapter(PriceTarget):
"""Adapter bridging LegacyXmlService to PriceTarget."""
def __init__(self, legacy: LegacyXmlService) -> None:
self._legacy = legacy
def get_price(self) -> float:
root = ET.fromstring(self._legacy.get_xml())
price_elem = root.find("price")
if price_elem is None or price_elem.text is None:
raise ValueError("Malformed XML: missing price tag")
return float(price_elem.text)
# Usage
adapter = XmlPriceAdapter(LegacyXmlService())
print(f"Price via adapter: ${adapter.get_price():.2f}")
Java (Object Adapter Composition)
// Adaptee: Legacy component with incompatible interface
public class LegacyFahrenheitSensor {
public double readFahrenheit() {
return 98.6;
}
}
// Target interface expected by client code
public interface MetricTemperatureSensor {
double getCelsius();
}
// Adapter bridging the two interfaces
public class TemperatureAdapter implements MetricTemperatureSensor {
private final LegacyFahrenheitSensor legacySensor;
public TemperatureAdapter(LegacyFahrenheitSensor legacySensor) {
this.legacySensor = legacySensor;
}
@Override
public double getCelsius() {
return (legacySensor.readFahrenheit() - 32.0) * (5.0 / 9.0);
}
}
C++
#include <iostream>
class LegacySensor {
public:
double readRawVolts() const { return 3.3; }
};
class MetricTarget {
public:
virtual ~MetricTarget() = default;
virtual double getPressureKPa() const = 0;
};
class SensorAdapter : public MetricTarget {
public:
explicit SensorAdapter(const LegacySensor& legacy) : legacy_(legacy) {}
double getPressureKPa() const override {
return legacy_.readRawVolts() * 30.0; // Voltage to kPa translation
}
private:
const LegacySensor& legacy_;
};
8. The Decorator Pattern (Structural)
Core Concept & Intent
The GoF Decorator Pattern wraps an existing object dynamically to layer on additional responsibilities without subclassing or modifying the underlying object.
Multi-Language Implementations
Python
from abc import ABC, abstractmethod
class DataSource(ABC):
@abstractmethod
def read(self) -> str:
pass
class FileDataSource(DataSource):
def read(self) -> str:
return "CONFIDENTIAL_FINANCIAL_REPORT"
class EncryptionDecorator(DataSource):
def __init__(self, source: DataSource) -> None:
self._source = source
def read(self) -> str:
raw = self._source.read()
return f"ENCRYPTED({raw})"
Java (Polymorphic Wrapping)
public interface DataSource {
String read();
}
public class FileDataSource implements DataSource {
@Override
public String read() {
return "CONFIDENTIAL_FINANCIAL_REPORT";
}
}
public abstract class DataSourceDecorator implements DataSource {
protected final DataSource wrappee;
public DataSourceDecorator(DataSource source) {
this.wrappee = source;
}
@Override
public String read() {
return wrappee.read();
}
}
public class EncryptionDecorator extends DataSourceDecorator {
public EncryptionDecorator(DataSource source) { super(source); }
@Override
public String read() {
return "ENCRYPTED(" + super.read() + ")";
}
}
// Dynamic composition at runtime:
// DataSource secure = new EncryptionDecorator(new FileDataSource());
// System.out.println(secure.read());
C++
#include <iostream>
#include <memory>
#include <string>
class Logger {
public:
virtual ~Logger() = default;
virtual void log(const std::string& msg) = 0;
};
class ConsoleLogger : public Logger {
public:
void log(const std::string& msg) override {
std::cout << "[LOG] " << msg << "\n";
}
};
class TimestampDecorator : public Logger {
public:
explicit TimestampDecorator(std::unique_ptr<Logger> logger) : logger_(std::move(logger)) {}
void log(const std::string& msg) override {
logger_->log("2026-09-26T11:00:00Z " + msg);
}
private:
std::unique_ptr<Logger> logger_;
};
9. The Strategy Pattern (Behavioral)
Core Concept & Intent
The Strategy Pattern encapsulates a family of algorithms into interchangeable components, allowing client callers to swap algorithms at runtime without modifying client code.
Multi-Language Implementations
Python
from typing import Callable, List
# Strategies encapsulated as clean, testable callables
def vwap_execution_strategy(prices: List[float]) -> str:
avg = sum(prices) / len(prices)
return f"VWAP execution filled at avg price: ${avg:.2f}"
def limit_passive_strategy(prices: List[float]) -> str:
best = min(prices)
return f"Passive limit order placed at best bid: ${best:.2f}"
class OrderRouter:
def __init__(self, strategy: Callable[[List[float]], str]) -> None:
self.strategy = strategy
def set_strategy(self, strategy: Callable[[List[float]], str]) -> None:
self.strategy = strategy
def route_order(self, book_depth: List[float]) -> str:
return self.strategy(book_depth)
# Usage
depth = [142.10, 142.25, 142.50, 142.80]
router = OrderRouter(strategy=vwap_execution_strategy)
print(router.route_order(depth))
# Swap execution algorithm dynamically at runtime
router.set_strategy(limit_passive_strategy)
print(router.route_order(depth))
Java (Functional Interface & Method References)
import java.util.List;
@FunctionalInterface
public interface PricingStrategy {
double calculatePrice(double basePrice);
}
public class OrderContext {
private PricingStrategy strategy;
public OrderContext(PricingStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(PricingStrategy strategy) {
this.strategy = strategy;
}
public double getFinalPrice(double base) {
return strategy.calculatePrice(base);
}
}
// Usage with Lambdas:
PricingStrategy normal = price -> price;
PricingStrategy holidayDiscount = price -> price * 0.80;
OrderContext order = new OrderContext(normal);
System.out.println(order.getFinalPrice(100.0)); // 100.0
order.setStrategy(holidayDiscount);
System.out.println(order.getFinalPrice(100.0)); // 80.0
C++
#include <iostream>
#include <functional>
#include <vector>
class RouteStrategy {
public:
virtual ~RouteStrategy() = default;
virtual void calculateRoute(const std::string& from, const std::string& to) = 0;
};
class FastRoute : public RouteStrategy {
public:
void calculateRoute(const std::string& from, const std::string& to) override {
std::cout << "Fastest highway route from " << from << " to " << to << "\n";
}
};
class Navigator {
public:
explicit Navigator(std::unique_ptr<RouteStrategy> strategy) : strategy_(std::move(strategy)) {}
void navigate(const std::string& from, const std::string& to) {
strategy_->calculateRoute(from, to);
}
private:
std::unique_ptr<RouteStrategy> strategy_;
};
10. The Chain of Responsibility Pattern (Behavioral)
Core Concept & Intent
The Chain of Responsibility Pattern passes a request along a sequential pipeline of handlers. Each handler decides either to process the request, modify it, or forward it to the next link in the chain. It is the basis for HTTP middlewares across modern web frameworks.
Multi-Language Implementations
Python
from abc import ABC, abstractmethod
from typing import Any, Dict, Optional
class Handler(ABC):
def __init__(self) -> None:
self._next: Optional["Handler"] = None
def set_next(self, handler: "Handler") -> "Handler":
self._next = handler
return handler # Enables fluent chaining: h1.set_next(h2).set_next(h3)
@abstractmethod
def handle(self, request: Dict[str, Any]) -> Optional[str]:
if self._next is not None:
return self._next.handle(request)
return None
class AuthenticationHandler(Handler):
def handle(self, request: Dict[str, Any]) -> Optional[str]:
token = request.get("token")
if token != "secret-token":
return "401 Unauthorized: Invalid API Token"
return super().handle(request)
class RoleValidationHandler(Handler):
def handle(self, request: Dict[str, Any]) -> Optional[str]:
role = request.get("role")
if role != "ADMIN":
return "403 Forbidden: Administrator role required"
return super().handle(request)
# Usage
pipeline = AuthenticationHandler()
pipeline.set_next(RoleValidationHandler())
request = {"token": "secret-token", "role": "ADMIN"}
result = pipeline.handle(request)
print(f"Pipeline Result: {'SUCCESS' if result is None else result}")
Java (Middleware Pipeline)
public abstract class Middleware {
private Middleware next;
public Middleware setNext(Middleware next) {
this.next = next;
return next;
}
public boolean check(String token, String role) {
if (next != null) {
return next.check(token, role);
}
return true;
}
}
public class AuthenticationMiddleware extends Middleware {
@Override
public boolean check(String token, String role) {
if (token == null || !token.equals("secret-token")) {
System.out.println("401 Unauthorized: Invalid Token");
return false;
}
return super.check(token, role);
}
}
public class RoleMiddleware extends Middleware {
@Override
public boolean check(String token, String role) {
if (!"ADMIN".equals(role)) {
System.out.println("403 Forbidden: Insufficient Permissions");
return false;
}
return super.check(token, role);
}
}
// Chaining:
// Middleware chain = new AuthenticationMiddleware();
// chain.setNext(new RoleMiddleware());
// boolean allowed = chain.check("secret-token", "ADMIN");
C++
#include <iostream>
#include <memory>
#include <string>
struct HttpRequest {
std::string ip;
bool isAuthenticated;
};
class MiddlewareHandler {
public:
virtual ~MiddlewareHandler() = default;
std::shared_ptr<MiddlewareHandler> setNext(std::shared_ptr<MiddlewareHandler> next) {
next_ = next;
return next;
}
virtual bool handle(const HttpRequest& req) {
if (next_) return next_->handle(req);
return true;
}
private:
std::shared_ptr<MiddlewareHandler> next_;
};
class AuthCheck : public MiddlewareHandler {
public:
bool handle(const HttpRequest& req) override {
if (!req.isAuthenticated) {
std::cout << "Auth failed!\n";
return false;
}
return MiddlewareHandler::handle(req);
}
};
Architectural Decision Matrix
WHAT IS YOUR ARCHITECTURAL PROBLEM?
│
┌───────────────────────────────┼───────────────────────────────┐
▼ ▼ ▼
[OBJECT CREATION] [STRUCTURE & MEMORY] [BEHAVIOR & EVENTS]
│ │ │
├─ Single global instance? ├─ Millions of small objects? ├─ 1-to-many event broadcast?
│ ► SINGLETON │ ► FLYWEIGHT │ ► OBSERVER
│ │ │
├─ Plugin/decorator catalog? ├─ Incompatible interfaces? ├─ Swap algorithm dynamically?
│ ► REGISTRY │ ► ADAPTER │ ► STRATEGY
│ │ │
├─ Complex step-by-step build? ├─ Add dynamic features? └─ Sequential request pipeline?
│ ► BUILDER │ ► DECORATOR ► CHAIN OF RESPONSIBILITY
│ │
└─ Abstract instantiation? └─ Composition over inheritance
► FACTORY METHOD
Conclusion
- In Python: First-class functions, metaclasses, decorators, and
__slots__replace heavy class scaffolding. - In Java: Strong static typing,
records, functional interfaces, and concurrency primitives (ConcurrentHashMap,CopyOnWriteArrayList) provide robust, thread-safe enterprise implementations. - In C++: RAII, smart pointers (
std::unique_ptr,std::shared_ptr), templates, and move semantics eliminate memory management hazards while maximizing execution performance.
Understanding how each language idiomatically models these patterns empowers you to design cleaner, maintainable, and high-performance software across any technology stack.