Low-Level Design — Quick Summary
Quick revision: every topic, key terms, and mnemonics for Low-Level Design.
This is a quick revision doc covering all 33 topics in lld. Open the linked notes if you want depth.
Foundations
What is Low-Level Design?
What it is. Designing the code structure of a system — classes, interfaces, methods, relationships. The blueprint for how we’d actually write code.
Key terms.
- HLD — components + how they communicate (DBs, services, queues).
- LLD — code structure inside components (classes, patterns, methods).
- Interview format (45–60 min) — Requirements (5–10 min) → Class Design (10–15 min) → Code (20–30 min) → Extensions.
Remember. Interviewers want: requirement gathering, class identification with right responsibilities, relationships, design patterns, extensibility, clean code. Red flag = god class doing everything.
OOP: The Four Pillars
What it is. Encapsulation, Abstraction, Inheritance, Polymorphism.
Key terms.
- Encapsulation — bundle data + methods, hide internal state. TV remote analogy.
- Abstraction — hide complex implementation behind simple interface. Car steering wheel.
- Inheritance — child reuses parent code. “Dog is an Animal.”
- Polymorphism — same method name, different behavior per type. “Open” a door vs file.
Remember. Encapsulation hides data; abstraction hides complexity. Polymorphism is what makes for shape in shapes: shape.area() work without knowing types.
Composition vs Inheritance
What it is. Two ways to reuse behavior. Favor composition over inheritance.
Key terms.
- Inheritance — “is-a.” Dog is an Animal. Good for shallow (1-2 levels), clear hierarchy.
- Composition — “has-a.” Car has an Engine. Mix and match abilities.
- Diamond / fragile base class problem — deep inheritance trees break when requirements change.
Remember. Start with composition. Reach for inheritance only when “is-a” is obvious and depth ≤ 3 levels. Composition lets us mix abilities (FightAbility + FlyAbility + MagicAbility) without explosion.
Abstract Classes vs Interfaces
What it is. Two ways to define contracts.
Key terms.
- Abstract class — partial implementation, can have state, single inheritance. “Is-a, specialized version.”
- Interface — pure contract, no state, multiple implementations. “Can-do, has this capability.”
Remember. Dog extends Animal (abstract — IS an animal). Dog implements Trainable (interface — CAN be trained). Most patterns (Strategy, Observer, Factory) use interfaces.
SOLID Principles
Cheatsheet — SOLID
| Letter | Principle | One-line |
|---|---|---|
| S | Single Responsibility | One class, one reason to change |
| O | Open/Closed | Open for extension, closed for modification |
| L | Liskov Substitution | Subclasses must be substitutable for parents |
| I | Interface Segregation | No class forced to implement methods it doesn’t use |
| D | Dependency Inversion | Depend on abstractions, not concretes |
Remember. SOLID = SRP / OCP / LSP / ISP / DIP. Each principle solves a different smell — SRP fights god classes, OCP fights if-else explosions, LSP fights surprising overrides, ISP fights fat interfaces, DIP fights tight coupling.
Single Responsibility Principle (SRP)
What it is. A class should have one reason to change.
Red flags. Class name has “And” or “Manager.” Methods don’t use each other. Class grows past ~500 lines. Unrelated changes touch the same class.
Remember. SRP isn’t “one method per class.” UserService with create/update/delete/find is fine — all manage user data. The question: how many reasons to change? UserManager doing user creation + email sending + logging = 3 reasons = split it.
Open/Closed Principle (OCP)
What it is. Open for extension, closed for modification.
Key terms.
- Replace
if/elifchains with polymorphism (Strategy pattern). - Define interface → write concrete implementations → consuming code depends on interface.
Remember. Adding a new payment type should mean adding a class, not modifying existing code. The OCP recipe: abstraction → implementations → depend on abstraction.
Liskov Substitution Principle (LSP)
What it is. If B extends A, anywhere we use A we should be able to use B without surprises.
Red flags.
- Subclass throws exceptions parent doesn’t (Penguin.fly() throws).
- Subclass override does nothing.
- Subclass changes behavior surprisingly (Square.setWidth also sets height).
- Code uses
instanceof/isinstanceto handle subclass differences.
Remember. Classic violation: Square extends Rectangle. The fix: don’t force the inheritance — make both implement Shape interface. Subclasses strengthen parent promises, never weaken.
Interface Segregation Principle (ISP)
What it is. No class should be forced to implement methods it doesn’t use.
Red flags.
- Empty method bodies.
- “I only use 2 of 10 methods.”
- Adding to an interface forces unrelated implementers to change.
Remember. RobotWorker forced to implement eat() and sleep() is the textbook violation. Split fat interfaces (Worker) into small focused ones (Workable, Eatable, Sleepable). Each class implements only what it needs.
Dependency Inversion Principle (DIP)
What it is. Depend on abstractions, not concretes. Inject dependencies from outside.
Key terms.
- Constructor injection (preferred) — receive deps in constructor.
- Setter injection — set after construction.
- Method injection — pass per call.
Remember. NotificationService shouldn’t new EmailSender() itself — accept a MessageSender interface in the constructor. Now we can swap Email/SMS/Slack/MockSender. DIP is what makes everything else testable.
Design Principles
DRY, KISS, and YAGNI
Key terms.
- DRY (Don’t Repeat Yourself) — single source of truth. But beware premature abstraction.
- KISS (Keep It Simple, Stupid) — readable beats clever. Don’t over-engineer simple things.
- YAGNI (You Ain’t Gonna Need It) — build what’s needed now, not what we might need.
Remember. Cost of YAGNI violations: time, complexity, bugs, maintenance for nobody. In LLD interviews: don’t add interfaces and abstractions until there’s a real reason.
Coupling and Cohesion
What it is. Quality metrics for design.
Key terms.
- Coupling — how much one class depends on another. We want LOW coupling.
- Cohesion — how related the responsibilities within a class are. We want HIGH cohesion.
Quick gut checks.
- “If I change A, how many other classes break?” Many = high coupling = bad.
- “Can I describe this class in one sentence without ‘and’?” If no, low cohesion = bad.
Remember. Low coupling, high cohesion is the result of following SOLID. SRP → cohesion. DIP → less coupling. ISP → cohesive interfaces. OCP → less concrete coupling.
UML Class Diagrams
What it is. Visual sketch language for class relationships.
Key terms.
- + public, - private, # protected — visibility markers.
- Association (A → B) — knows about.
- Aggregation (A ◇→ B) — has, but B can exist alone.
- Composition (A ◆→ B) — owns, B dies with A.
- Inheritance (B ▷ A, solid line) — is-a.
- Implementation (B ▷ A, dashed) — implements interface.
- Dependency (A ⤍ B, dashed) — temporarily uses.
Remember. Speed > perfection. Boxes first, arrows later. Talk while drawing. Composition for “owns lifecycle.” Aggregation for “has, independent.”
Creational Design Patterns
Singleton Pattern
What it is. Only one instance of a class, with global access.
Key terms.
- Private constructor — no one can
new. - Static getInstance() — creates on first call, returns same instance after.
- Double-checked locking — thread-safe pattern (check, lock, check again).
volatilein Java for visibility across threads.
Remember. Use for DB pools, loggers, configs, caches. Beware — singletons = global state = hard to test. Don’t use just because we can.
Factory Pattern
What it is. Centralize object creation. Two flavors:
- Factory Method — one method creates one product (or subclasses pick which to create).
- Abstract Factory — creates families of related products (UI themes: Button + Checkbox + Input that all match).
Remember. Replaces if-else for type-based instantiation. Factory Method = one product type. Abstract Factory = family of matching products. Eliminates “new ConcreteClass()” everywhere.
Builder Pattern
What it is. Build complex objects step by step. Fluent chaining.
Key terms.
- Telescoping constructor problem —
new House(4, 2, true, false, true, ...)is unreadable. - Each setter returns
this→ chaining. build()assembles and returns the final object.
Remember. Use for 4+ optional parameters. Pizza.builder().size("large").addCheese().addPepperoni().build(). Below 3-4 params, just use a constructor.
Prototype Pattern
What it is. Create new objects by cloning existing ones.
Key terms.
- Shallow copy — top-level only, nested objects are shared references (dangerous).
- Deep copy — everything duplicated, fully independent.
- Prototype registry — map of pre-configured templates to clone from.
Remember. Use when construction is expensive (DB query, file I/O) or when copying without knowing concrete class. Always deep-copy if there are nested objects.
Structural Design Patterns
Adapter Pattern
What it is. Wrap an incompatible class to match the interface our code expects.
Key terms.
- Object adapter (composition) — preferred.
- Class adapter (inheritance) — needs multiple inheritance.
- The adapter implements target interface + holds reference to adaptee.
Remember. Use for third-party libraries with different signatures or legacy code. Adapter is a translator — neither side changes, the middleman handles translation.
Decorator Pattern
What it is. Add behavior to objects by wrapping them. Stack layers like LEGO.
Key terms.
- Decorator implements same interface as wrapped object.
- Holds reference to inner object, delegates + adds behavior.
- Avoids class explosion (3 features × inheritance = 8 classes; decorators = 3 classes).
Remember. Coffee + Milk + Sugar + WhippedCream — each is a decorator wrapping the previous. Real-world: Java I/O streams, Express middleware. Decorator enhances the wrapped object.
Facade Pattern
What it is. Simple interface in front of complex subsystem.
Key terms.
- Doesn’t add new functionality, just simplifies access.
homeTheater.watchMovie()instead of 7 separate calls to TV/Speakers/BluRay/Lights.
Remember. “Restaurant waiter coordinating chef + dishwasher + sommelier.” Real-world: jQuery, ORMs, AWS SDK, Express. Facade simplifies; Adapter translates; Proxy controls access.
Proxy Pattern
What it is. Surrogate that controls access to the real object. Same interface.
Key terms.
- Virtual proxy — lazy initialization (image loads on first display).
- Protection proxy — access control (admin-only methods).
- Caching proxy — cache results.
- Remote proxy — represent object on another server (RPC stubs).
Remember. Proxy controls. Decorator enhances. Adapter translates. Use for lazy loading, access control, caching, logging, remote access.
Behavioral Design Patterns
Observer Pattern
What it is. One-to-many: subject changes → all observers notified automatically.
Key terms.
- Subject (Publisher) — keeps list, notifies on change.
- Observer (Subscriber) — implements
update(). - Push model — subject sends data. Pull model — subject signals, observers fetch.
- Pub/Sub — same idea but with a message broker middleman.
Remember. YouTube subscriptions analogy. Use for events, real-time UI, notifications, data binding (React/MobX). Always unsubscribe to avoid memory leaks.
Strategy Pattern
What it is. Family of interchangeable algorithms. Pick one at runtime.
Key terms.
- Each algorithm is its own class implementing a common interface.
- Context holds reference to current strategy and delegates.
- Eliminates if-else chains for algorithm selection.
Remember. Payment methods, discount calculators, sorting algorithms, navigation routes. Strategy = client picks the algorithm.
State vs Strategy (interview favorite)
| State | Strategy | |
|---|---|---|
| Who switches? | States transition themselves | Client picks |
| States know each other? | Yes | No |
| Purpose | Object lifecycle | Algorithm swap |
| Example | Order: Placed → Shipped → Delivered | Payment: Card / PayPal / Crypto |
Command Pattern
What it is. Encapsulate a request as an object with execute() and undo().
Key terms.
- Invoker triggers; Command wraps the request; Receiver does the work.
- Enables undo/redo, queueing, logging, transactions, macro recording.
Remember. Restaurant order slip analogy. Editor undo/redo is the canonical example. To undo: keep history stack. To redo: keep redo stack. Implementing transactions: execute commands; on failure, run undo() in reverse.
State Pattern
What it is. Object’s behavior changes based on internal state. Each state is its own class.
Key terms.
- States transition to other states themselves.
- Each state implements all the same methods, with state-specific behavior.
- Replaces giant
if state == Xchains in every method.
Remember. Vending machine: Idle → HasMoney → Dispensing. ATM: Idle → Auth → Menu. Each state controls what’s allowed. New state? New class, no existing code touched.
Template Method Pattern
What it is. Define algorithm skeleton in base class; subclasses override specific steps.
Key terms.
- Template method — the orchestrator (should be
finalin Java). - Abstract methods — subclasses MUST override.
- Hook methods — subclasses CAN override (default does nothing).
- Inheritance-based (vs Strategy which is composition-based).
Remember. Data processing pipelines, game loops, web framework hooks. The flow is fixed; only specific steps vary. ETL: read → parse (varies) → validate → output.
Cheatsheet — Pattern Categories
| Category | Patterns | What they do |
|---|---|---|
| Creational | Singleton, Factory, Builder, Prototype | Object creation |
| Structural | Adapter, Decorator, Facade, Proxy | Class composition |
| Behavioral | Observer, Strategy, Command, State, Template | Object collaboration |
Real LLD Questions
Design a Parking Lot
Core entities. ParkingLot (Singleton) → Floors → ParkingSpots. Vehicle (Car/Bike/Truck). Ticket. PricingStrategy.
Key concepts.
- Vehicle to Spot mapping — Bike→Small, Car→Medium, Truck→Large.
- Singleton for the lot itself (one instance).
- Strategy for pricing (HourlyPricing, can swap to DayPricing/SurgePricing).
- Each Spot tracks
vehicle(None when empty). - Each Floor’s
find_available_spot(vehicle_type)does the lookup.
Remember. Composition: ParkingLot has Floors, Floor has Spots. Don’t make a ParkingLotManager that does everything. Pricing pluggable = OCP. Extensions: valet, EV charging, reserved spots, multiple gates, dynamic pricing.
Design an Elevator System
Core entities. ElevatorSystem → Elevators + SchedulingStrategy. Each Elevator has Door, Display, Direction, up/down request sets.
Key concepts.
- LOOK algorithm — serve all requests in current direction, then reverse. Don’t go past the highest/lowest request.
- Strategy for elevator selection (NearestElevator, ZoneBased, RoundRobin).
- External request (UP/DOWN on a floor) vs Internal request (floor button inside).
- Score = idle_distance OR same_direction_distance OR ∞ (going wrong way).
Remember. Use a TreeSet/sorted structure for up/down requests for O(log n) min/max. The hardest part is the scheduling decision — Strategy pattern fits perfectly. Extensions: priority floors, emergency mode, weight limit, zone scheduling, VIP elevator.
Design BookMyShow
Core entities. Movie, Theater, Screen, Show, Seat, Booking, Payment. Show ties Movie + Screen + StartTime.
Key concepts (the seat-locking problem is the heart).
- Seat states: AVAILABLE → LOCKED → BOOKED.
- Lock seats for 5 minutes when user starts checkout.
- Atomic check-and-lock (
synchronized/Lock) prevents race conditions. - Background lock expiry releases timed-out seats.
- Booking states: PENDING → CONFIRMED / CANCELLED / EXPIRED.
Remember. Without locking, two users can book the same seat. Use pessimistic locking with TTL. SeatPrice depends on SeatType (REGULAR/PREMIUM/VIP). Extensions: coupons (Strategy), food orders, refund policy (Strategy), waitlist (Observer), dynamic pricing.
Design a Vending Machine
Core entities. VendingMachine (context) + State (Idle/HasMoney/Dispensing) + Inventory + Product.
Key concepts.
- State pattern is THE pattern here. Same action (insertMoney/selectProduct) behaves differently per state.
- IdleState — accepts money → HasMoneyState.
- HasMoneyState — accepts more money / select product (validate balance + stock) → DispensingState. Cancel refunds.
- DispensingState — dispenses, returns change → IdleState.
- Inventory tracks products + quantities; reduces on dispense.
Remember. Without State pattern, every method is a giant if state == X chain. Each state class handles what’s valid in that state. Extensions: card payment, admin refill, multiple-product cart, denomination handling, display.
Design Snake & Ladder
Core entities. Game → Board + Players + Dice. Board has Snakes + Ladders.
Key concepts.
- Composition over inheritance — Snake and Ladder don’t share a base class.
- Board’s
getNewPosition(current, dice)handles boundaries, snakes, ladders. - If new position > 100, stay put.
- Dice roll → Board calculates → Player position updates → check win.
Remember. Each class one job: Dice rolls, Board calculates positions, Player tracks state, Game manages turns. Snakes use Map (head→tail), Ladders use Map (bottom→top). Extensions: multiple dice, special cells (power-ups), save/resume (Memento), chained snakes/ladders.
Design Chess
Core entities. Game → Board + Players. Board has 8x8 grid of Pieces. Six piece types: King/Queen/Rook/Bishop/Knight/Pawn.
Key concepts.
- Polymorphism is the star. Abstract
Piece.canMove()overridden by each piece type. - Game just calls
piece.canMove()— doesn’t care which piece. - King — 1 square any direction. Queen — straight or diagonal. Rook — straight. Bishop — diagonal. Knight — L-shape, jumps. Pawn — forward 1 (or 2 from start), captures diagonal.
- Validate: own piece + valid move + path clear (
isPathClear) + own king not in check after move.
Remember. findKing(color) and isUnderAttack(row, col, byColor) are the helpers for check detection. After moving, if our king is attacked, undo. Adding new piece type = new class, no other changes. Extensions: castling (track hasMoved), en passant (track lastMove), pawn promotion, undo (Command), checkmate detection (try all moves).
Design Library Management
Core entities. Library → Books + Members. Book has many BookItems. Member has many Loans.
Key concepts.
- Book vs BookItem distinction is critical. Book = catalog entry (ISBN, title, author). BookItem = physical copy (barcode, status).
- Loan tracks: item, member, borrowDate, dueDate, returnDate. Calculates fine = overdue_days × rate.
- Member has MAX_LOANS limit.
- Observer pattern — waitlist notifications when book returned.
- BookStatus: AVAILABLE / LOANED / RESERVED / LOST.
Remember. Library acts as Facade. Borrow flow: find member → check limit → find available item → mark LOANED → create Loan. Return: calc fine → AVAILABLE → notify waitlist. Extensions: renewal, member tiers (Strategy), digital books, multi-criteria search (Builder).
Design ATM
Core entities. ATM (context) + ATMState (Idle/Auth/Menu/Transaction) + CashDispenser + Card + Account + Transaction.
Key concepts.
- State pattern drives everything. Card insertion in Idle → AuthState. Wrong PIN 3x → card retained, IdleState.
- AuthState has MAX_ATTEMPTS = 3.
- Account has balance + dailyWithdrawn (DAILY_LIMIT $5000).
- Withdraw: validate → debit account → dispense → succeed (or rollback on failure).
- Transactions logged for receipts.
Remember. Same buttons mean different things per state. State is THE pattern here. Cash dispenser tracks physical cash; reject if low. Extensions: multi-currency (denomination strategy), receipt printer (Observer), admin mode (new state), hardware failure recovery (Command rollback).