Design Patterns
Interview Priority — The 8 Patterns That Actually Get Asked
You don't need all 23 for interviews. Focus on these in order:
- Singleton — thread-safe implementation, when NOT to use it
- Factory / Abstract Factory — payment processors, notification channels
- Strategy — runtime algorithm switching (sorting, pricing rules)
- Observer — event systems, pub/sub, reactive streams
- Builder — complex object construction (think HTTP request builders)
- Decorator — I/O streams, middleware chains, logging wrappers
- Adapter — legacy system integration, third-party library wrapping
- 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
Creational Patterns
How objects get created
Structural Patterns
How objects are composed
Behavioral Patterns
How objects communicate
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.