StudyComputer ScienceDesign Patterns

Introduction to Design Patterns

2026-03-09 3 min read Computer Science
Introduction to Design Patterns

What Are Design Patterns?

Design patterns are reusable solutions to commonly occurring problems in software design. They are not finished code that can be directly transformed into source code but rather templates for how to solve problems in different situations.

The concept was popularized by the “Gang of Four” (GoF) in their 1994 book Design Patterns: Elements of Reusable Object-Oriented Software.

“Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem.” — Christopher Alexander

Categories of Design Patterns

Design patterns are typically divided into three categories:

CategoryPurposeExamples
CreationalObject creation mechanismsSingleton, Factory, Builder
StructuralObject compositionAdapter, Decorator, Facade
BehavioralObject communicationObserver, Strategy, Command

The Singleton Pattern

The Singleton pattern ensures a class has only one instance and provides a global point of access to it.

When to Use

  • Database connections
  • Configuration managers
  • Logging services
  • Thread pools

Implementation in Python

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super().__new__(cls)
        return cls._instance

# Usage
config1 = Singleton()
config2 = Singleton()
assert config1 is config2  # True - same instance

Implementation in C

public sealed class Singleton
{
    private static readonly Lazy<Singleton> _instance =
        new Lazy<Singleton>(() => new Singleton());

    private Singleton() { }

    public static Singleton Instance => _instance.Value;
}

The Observer Pattern

The Observer pattern defines a one-to-many dependency between objects. When one object (the subject) changes state, all its dependents (observers) are notified.

Real-World Analogy

Think of a newspaper subscription: the publisher (subject) sends newspapers to subscribers (observers) whenever a new edition is released.

Implementation in Python

from abc import ABC, abstractmethod

class Subject:
    def __init__(self):
        self._observers = []

    def attach(self, observer):
        self._observers.append(observer)

    def detach(self, observer):
        self._observers.remove(observer)

    def notify(self, data):
        for observer in self._observers:
            observer.update(data)

class Observer(ABC):
    @abstractmethod
    def update(self, data):
        pass

class PriceAlert(Observer):
    def __init__(self, name):
        self.name = name

    def update(self, data):
        print(f"[{self.name}] Price updated: {data}")

# Usage
market = Subject()
trader = PriceAlert("Trading Desk")
risk = PriceAlert("Risk Management")

market.attach(trader)
market.attach(risk)
market.notify({"AAPL": 150.25})

The Strategy Pattern

The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable.

Use Case in Finance

Different pricing models for financial instruments:

from abc import ABC, abstractmethod

class PricingStrategy(ABC):
    @abstractmethod
    def calculate_price(self, instrument):
        pass

class BlackScholes(PricingStrategy):
    def calculate_price(self, instrument):
        # Black-Scholes pricing model
        return "Price via Black-Scholes"

class MonteCarlo(PricingStrategy):
    def calculate_price(self, instrument):
        # Monte Carlo simulation
        return "Price via Monte Carlo"

class PricingEngine:
    def __init__(self, strategy: PricingStrategy):
        self._strategy = strategy

    def price(self, instrument):
        return self._strategy.calculate_price(instrument)

# Usage - easily swap strategies
engine = PricingEngine(BlackScholes())
print(engine.price("EUR/USD Option"))

engine = PricingEngine(MonteCarlo())
print(engine.price("Exotic Derivative"))

Key Takeaways

  1. Don’t over-engineer: Use patterns when they solve a real problem, not to show off
  2. Know the trade-offs: Each pattern has pros and cons
  3. Composition over inheritance: Most modern patterns favor composition
  4. SOLID principles: Design patterns often implement SOLID principles naturally

Further Reading

  • Design Patterns: Elements of Reusable Object-Oriented Software by GoF
  • Head First Design Patterns by Eric Freeman
  • Refactoring to Patterns by Joshua Kerievsky
PreviousUnderstanding Options Pricing: Black-Scholes and Beyond