← Back to Notes

Low-Level Design Patterns

2026-01-25article
Originally Published ↗Download PDF ⬇

Low-Level Design Patterns

Design patterns are reusable solutions to common design problems. While the original "Gang of Four" (GoF) book defined 23 patterns, modern low-level design (LLD) interviews typically focus on a smaller subset that are relevant to current software development practices. This guide cuts through the historical baggage to focus on the patterns that actually appear in interviews, categorized into Creational, Structural, and Behavioral patterns.

Creational Patterns

Creational patterns handle object creation mechanisms, promoting flexibility and code reuse.

Factory Method

A Factory helps create objects without specifying the exact class of object that will be created. It focuses on "how do you create something?" and comes up often when requirements involve supporting different types (e.g., "handle multiple payment methods" or "support different notification types"). It centralizes creation logic so calling code doesn't need to change when new types are added.

Builder

The Builder pattern constructs complex objects step-by-step. It is useful when an object has many optional parts or configuration options (e.g., HTTP requests, database queries). Instead of a constructor with numerous parameters, you build the object incrementally. Note that in Python, this is often less necessary due to keyword arguments and default values.

Singleton

Ensures a class has only one instance and provides a global point of access to it. While common in languages like Java for shared resources (connection pools, loggers), it is generally considered an anti-pattern in Python where module-level variables or dependency injection are preferred.

Structural Patterns

Structural patterns explain how to assemble objects and classes into larger structures while keeping these structures flexible and efficient.

Decorator

Attaches new behaviors to objects by placing these objects inside special wrapper objects. This is used when you need to layer extra functionality at runtime (e.g., adding logging, encryption, or compression) without modifying the underlying class or creating an explosion of subclasses.

Facade

Provides a simplified interface to a library, a framework, or any other complex set of classes. In LLD interviews, this often manifests as the main "Orchestrator" or "Game" class that coordinates multiple underlying components. You might use this instinctively without naming it.

Behavioral Patterns

Behavioral patterns take care of effective communication and the assignment of responsibilities between objects.

Strategy

The most common interview pattern. Strategy allows you to define a family of algorithms, put each of them into a separate class, and make their objects interchangeable. It replaces complex conditional logic (if/else chains based on type) with polymorphism. Use it when you have different ways of doing the same thing (e.g., different payment strategies like CreditCard vs PayPal) and want to swap them at runtime.

Observer

Lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they're observing. This is essential for systems where state changes need to propagate to multiple components (e.g., stock price updates, user activity notifications).

State Machine

Allows an object to alter its behavior when its internal state changes. This is critical for systems with complex state transitions like Vending Machines, Order Processing flows, or Game interactions. Instead of conditional logic checking current_state everywhere, each state behavior is encapsulated in its own class.

Key Concepts

  • Factory Pattern: Centralizes object creation to decouple logic from specific classes.
  • Strategy Pattern: Enables swapping behaviors (algorithms) at runtime using polymorphism; replaces conditional logic.
  • Observer Pattern: Implements a publish/subscribe mechanism for one-to-many dependency updates.
  • Decorator Pattern: Dynamically adds behavior to an object by wrapping it.
  • State Pattern: Encapsulates state-specific behaviors and transitions into separate classes.
  • Facade Pattern: Hides system complexity behind a simple, unified interface.
  • Over-engineering: A common pitfall in interviews; only use patterns when the problem naturally demands them.