Skip to content
3 min read

Design Patterns

Interview Priority — The 8 Patterns That Actually Get Asked

You don't need all 23 for interviews. Focus on these in order:

  1. Singleton — thread-safe implementation, when NOT to use it
  2. Factory / Abstract Factory — payment processors, notification channels
  3. Strategy — runtime algorithm switching (sorting, pricing rules)
  4. Observer — event systems, pub/sub, reactive streams
  5. Builder — complex object construction (think HTTP request builders)
  6. Decorator — I/O streams, middleware chains, logging wrappers
  7. Adapter — legacy system integration, third-party library wrapping
  8. Proxy — lazy loading, access control, caching (Spring AOP uses this)

Master these 8 deeply (with code + real-world use case), then skim the remaining 15.

Why Do We Need Design Patterns?

%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '13px', 'fontFamily': 'Inter, -apple-system, sans-serif'}, 'flowchart': {'nodeSpacing': 30, 'rankSpacing': 50, 'padding': 12, 'curve': 'basis'}, 'sequence': {'actorMargin': 60, 'messageMargin': 40}, 'class': {'padding': 12}}}%%
flowchart LR
    A["🖥️ Start:<br/>Simple Code"] --> B["🕸️ As Features Grow:<br/>• more if-else<br/>• duplicate logic<br/>• hard to change"]
    B --> C["🎯 Design Patterns:<br/>✅ Clean code<br/>✅ Easy to extend<br/>✅ Reusable solutions<br/>✅ Easy to maintain"]

What are Design Patterns?

Design patterns are proven solutions to common software design problems. They are not code — they are templates for how to solve problems that can be used in many different situations.

Practice Repository

Full Java implementations of all patterns: lld-Design-Patterns


Types of Design Patterns

%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '13px', 'fontFamily': 'Inter, -apple-system, sans-serif'}, 'flowchart': {'nodeSpacing': 30, 'rankSpacing': 50, 'padding': 12, 'curve': 'basis'}, 'sequence': {'actorMargin': 60, 'messageMargin': 40}, 'class': {'padding': 12}}}%%
flowchart LR
    DP{{"<b>DESIGN PATTERNS</b>"}} --> C(["① <b>CREATIONAL</b><br/>(Object Creation)"])
    DP --> S(["② <b>STRUCTURAL</b><br/>(Object Structure)"])
    DP --> B(["③ <b>BEHAVIORAL</b><br/>(Object Behavior)"])

① Creational Patterns — Object Creation

Problem

How to create different objects in a clean and flexible way without tying code to concrete classes?

Example: Payment method selection — UPI, Card, or Wallet. You don't want new UPIPayment() scattered everywhere.

Goal: Create objects without hard-coding the exact class to instantiate.

Used In: Payment systems, Notification systems, Document parsers

# Pattern What it Does
1 Singleton Ensures only ONE instance of a class exists globally
2 Factory Method Creates objects without specifying the exact class
3 Abstract Factory Creates families of related objects
4 Builder Constructs complex objects step by step
5 Prototype Creates new objects by cloning existing ones

② Structural Patterns — Object Structure

Problem

How to add new behavior or features to existing objects without changing their code?

Example: Add logging + authentication to every API call without modifying the API handler.

%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '13px', 'fontFamily': 'Inter, -apple-system, sans-serif'}, 'flowchart': {'nodeSpacing': 30, 'rankSpacing': 50, 'padding': 12, 'curve': 'basis'}, 'sequence': {'actorMargin': 60, 'messageMargin': 40}, 'class': {'padding': 12}}}%%
flowchart LR
    Client --> Decorator1["🔒 Authentication"]
    Decorator1 --> Decorator2["📝 Logging"]
    Decorator2 --> Server["🖥️ Server"]

Goal: Extend functionality without modifying existing code.

Used In: API wrappers, Adapters, Logging, Caching, Decorators

# Pattern What it Does
1 Adapter Makes incompatible interfaces work together
2 Decorator Adds behavior dynamically without subclassing
3 Facade Simplifies a complex subsystem with one interface
4 Proxy Controls access to another object
5 Composite Treats individual objects and compositions uniformly
6 Bridge Separates abstraction from implementation
7 Flyweight Shares objects to reduce memory usage

③ Behavioral Patterns — Object Behavior

Problem

How objects communicate and behave in different situations without tight coupling?

Example 1: Payment System — same interface, different logic (Strategy)

%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '13px', 'fontFamily': 'Inter, -apple-system, sans-serif'}, 'flowchart': {'nodeSpacing': 30, 'rankSpacing': 50, 'padding': 12, 'curve': 'basis'}, 'sequence': {'actorMargin': 60, 'messageMargin': 40}, 'class': {'padding': 12}}}%%
flowchart LR
    PI[["Payment Interface"]] --> UPI(["UPI Payment"])
    PI --> Card(["Card Payment"])
    PI --> Wallet(["Wallet Payment"])

Example 2: Notification System — one event, many users notified (Observer)

%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '13px', 'fontFamily': 'Inter, -apple-system, sans-serif'}, 'flowchart': {'nodeSpacing': 30, 'rankSpacing': 50, 'padding': 12, 'curve': 'basis'}, 'sequence': {'actorMargin': 60, 'messageMargin': 40}, 'class': {'padding': 12}}}%%
flowchart LR
    Event["🔔 Event"] --> U1["👤 User 1"]
    Event --> U2["👤 User 2"]
    Event --> U3["👤 User 3"]

Goal: Handle different behaviors and interactions between objects.

Used In: Notification systems, Event handling, Undo/Redo, Workflows

# Pattern What it Does
1 Observer Notifies multiple objects when state changes
2 Strategy Swaps algorithms at runtime
3 Command Encapsulates a request as an object
4 Chain of Responsibility Passes request along a chain of handlers
5 State Changes behavior when internal state changes
6 Template Method Defines skeleton, subclasses fill in steps
7 Iterator Traverses a collection without exposing internals
8 Mediator Reduces chaotic dependencies between objects
9 Memento Captures and restores object state (undo)
10 Visitor Adds operations without changing classes
11 Interpreter Evaluates sentences in a language

Quick Reference — All 23 Patterns


Think in Patterns, Write Better Code!

Don't memorize patterns — understand the problem each one solves. When you face a similar problem in your code, the right pattern will come naturally.