Six systems · all Track A patterns appliedCLICK CARD TO DEEP DIVE
01
Chess Game
State · Command · Observer · Factory
Move validation without revealing Board internals. Undo last N moves. Check/checkmate detection by simulation.
02
Elevator System
State · Strategy · Observer · Concurrent
LOOK algorithm. Multiple elevators sharing floor requests. Concurrent calls from many floors simultaneously.
03
Library Management
Builder · Observer · Iterator · Concurrent
Reservation queue per book. Fine calculation. Thread-safe borrowBook() when one copy remains.
04
Food Ordering
Facade · Strategy · Observer · CoR · State
Order lifecycle state machine. Surge pricing. CoR pipeline: validate→price→pay→dispatch→notify.
05
ATM Machine
State · Chain of Resp. · Command · Observer
PIN retry lock. Transaction atomicity. Cash dispensing chain. What if network fails mid-dispense?
06
Hotel Booking
Builder · Strategy · Observer · Concurrent
Concurrent room booking with date-range contention. Dynamic pricing. Reservation waitlist.
Pattern → Problem mapping
| SYSTEM | KEY PATTERN | CONCURRENCY CONCERN | KILLER INTERVIEW QUESTION |
|---|---|---|---|
| Chess | Command (move+undo), State (game phase) | Single-player — no concurrency | "How do you detect checkmate efficiently?" |
| Elevator | State (per elevator), Strategy (LOOK algo) | Concurrent floor requests → ReentrantLock per elevator | "How do you handle 1000 floors and 20 elevators?" |
| Library | Builder (Book), Observer (availability) | synchronized(book) for last-copy race | "Thread safety of borrowBook() when one copy remains?" |
| Food Ordering | CoR (pipeline), State (order lifecycle) | Idempotent payment retry, order status updates | "How to add a new payment method without touching OrderService?" |
| ATM | State (transaction), CoR (dispensing) | ReentrantLock on account debit+dispense atomicity | "What happens if network fails after debit but before dispense?" |
| Hotel | Builder (SearchCriteria), Strategy (pricing) | ReentrantLock per room for date-range booking | "10,000 users try to book the last room simultaneously?" |
01Chess
02Elevator
03Library
04Food
05ATM
06Hotel
01
Chess Game
STATE · COMMAND · OBSERVER · FACTORY METHOD
2 players, 8×8 board, 6 piece types. Move validation per piece. Check/checkmate detection by simulation. Undo last N moves. Game state serialization.
WAITING
→start
WHITE_TURN
→valid move
BLACK_TURN
→check
CHECK
→no escape
CHECKMATE
Command — Move
Each Move is a Command with execute() + undo(). Stores captured piece + firstMove state for perfect undo. History stack enables N-move rollback.
Factory Method — Piece
PieceFactory.create(type, color, pos) returns correct subclass. Client code never does new King() — decoupled from piece hierarchy.
Observer — Game Events
ChessGame notifies GameObserver on: moveMade, check, checkmate, gameOver. UI and sound engine are observers — completely decoupled.
Move.java — Command pattern with undoJAVA
class Move implements Command { private final Piece piece; private final Position from, to; private Piece capturedPiece; // Saved for undo private boolean wasFirstMove; // Pawn/king special rules public void execute(Board board) { capturedPiece = board.getPiece(to); wasFirstMove = piece.isFirstMove(); board.setPiece(to, piece); board.setPiece(from, null); piece.setPosition(to); piece.setFirstMove(false); } public void undo(Board board) { board.setPiece(from, piece); // Restore moving piece board.setPiece(to, capturedPiece); // Restore captured piece (null if none) piece.setPosition(from); piece.setFirstMove(wasFirstMove); } } // Checkmate detection — simulate all moves, check none escape check public boolean isCheckmate(Board board, PieceColor color) { if (!isCheck(board, color)) return false; return getAllPieces(board, color).stream() .flatMap(p -> p.validMoves(board).stream() .map(to -> new Move(p, p.getPosition(), to))) .noneMatch(m -> !wouldLeaveKingInCheck(m, board, color)); }
02
Elevator System
STATE · STRATEGY (LOOK) · OBSERVER · CONCURRENT
N elevators, M floors. LOOK algorithm (sweep up then down). Concurrent floor requests. Pluggable selection strategy for different scheduling algorithms.
IDLE
→request
MOVING_UP
→floor reached
STOPPED_OPEN
→no more up
MOVING_DOWN
→done
IDLE
State — per Elevator
Each elevator holds a state (IDLE/MOVING_UP/MOVING_DOWN/STOPPED). step() transitions automatically. No giant switch statement.
Strategy — Scheduling
ElevatorSelectionStrategy is injected into ElevatorController. Swap LOOK for FCFS or zone-based strategy without changing controller.
Concurrency — ReentrantLock
Each Elevator has its own ReentrantLock. addRequest() and step() are both synchronized per elevator — no contention between elevators.
Elevator.java — LOOK algorithm + concurrent requestsJAVA
class Elevator { private final TreeSet<Integer> upRequests = new TreeSet<>(); private final TreeSet<Integer> downRequests = new TreeSet<>(Comparator.reverseOrder()); private final ReentrantLock lock = new ReentrantLock(); private ElevatorState state = ElevatorState.IDLE; private int currentFloor = 1; // LOOK: service all requests in current direction, then reverse public void step() { lock.lock(); try { switch (state) { case MOVING_UP -> { if (!upRequests.isEmpty()) { currentFloor = upRequests.first(); // next floor up upRequests.remove(currentFloor); state = ElevatorState.STOPPED_OPEN; } else if (!downRequests.isEmpty()) { state = ElevatorState.MOVING_DOWN; // reverse } else { state = ElevatorState.IDLE; } } /* ... MOVING_DOWN, STOPPED_OPEN, IDLE cases ... */ } } finally { lock.unlock(); } } }
03
Library Management
BUILDER · OBSERVER · ITERATOR · CONCURRENCY
Book catalog, member management, borrowing/returning with fine calculation. Reservation queue notifies next member when book becomes available.
Builder — Book
Book has many optional attributes (genre, publisher, year). Builder prevents telescoping constructors and makes required fields explicit.
Observer — Availability
returnBook() triggers notification to next member in reservation queue. LibraryObserver decouples notification mechanism from core borrow logic.
Concurrency
synchronized(book) for last-copy race condition. ConcurrentLinkedQueue for reservation queue — safe concurrent enqueue/dequeue.
LibrarySystem.java — thread-safe last copy borrowingJAVA
public boolean borrowBook(String isbn, Member member) { Book book = catalog.get(isbn); if (book == null) throw new BookNotFoundException(isbn); if (book.getAvailable() == 0) { reservations.reserve(book, member); // Join waitlist return false; } // Synchronize on book object — prevents two threads taking last copy synchronized (book) { if (book.getAvailable() == 0) { // Double-check after sync reservations.reserve(book, member); return false; } book.decrementAvailable(); } activeBorrow.put(member.id+":"+isbn, new Borrowing(book, member)); return true; } public void returnBook(String isbn, Member member) { Borrowing b = activeBorrow.remove(member.id+":"+isbn); b.markReturned(); synchronized (b.getBook()) { b.getBook().incrementAvailable(); } // Notify next in queue reservations.nextInQueue(book).ifPresent(next -> observers.forEach(o -> o.onBookAvailable(book, next))); }
04
Online Food Ordering
FACADE · STRATEGY · OBSERVER · CHAIN OF RESPONSIBILITY · STATE
Complete order lifecycle state machine. Surge pricing strategy. CoR processing pipeline: validate → price → payment → delivery assignment → notification.
PLACED
→
ACCEPTED
→
PREPARING
→
READY
→
PICKED_UP
→
DELIVERED
OrderService.java — CoR pipeline + StrategyJAVA
// Chain: Validation → Payment → Delivery → Notification OrderHandler chain = new ValidationHandler(); chain.setNext(new PaymentHandler(paymentService)) .setNext(new DeliveryAssignmentHandler(deliveryService)) .setNext(new NotificationHandler(notifier)); // STRATEGY: surge pricing (pluggable at runtime) class SurgePricingStrategy implements PricingStrategy { public double calculateTotal(Order order) { double base = order.getItems().stream().mapToDouble(Item::getPrice).sum(); double surge = isPeakHour(order.getTime()) ? 1.3 : 1.0; return base * surge + DELIVERY_FEE; } } // Add new payment method: new class implementing PaymentHandler // No changes to ValidationHandler, DeliveryHandler, NotificationHandler (OCP)
05
ATM Machine
STATE · CHAIN OF RESPONSIBILITY · COMMAND · OBSERVER
PIN retry lockout, transaction atomicity, cash dispensing via CoR. Command enables transaction reversal if dispense fails after debit.
IDLE
→insert card
CARD_IN
→correct PIN
AUTH
→select txn
TXN_SELECTED
→dispense
COMPLETE
ATM — PIN retry + transaction atomicityJAVA
// PIN retry: 3 attempts then card retained class CardInsertedState implements ATMState { private int attempts = 0; public void enterPin(ATM atm, String pin) { if (atm.getBank().verifyPin(atm.getCurrentCard(), pin)) { atm.setState(new AuthenticatedState()); } else if (++attempts >= 3) { atm.getCardReader().retainCard(); // Swallow card atm.setState(new IdleState()); atm.display("Card retained — 3 failed attempts"); } } } // Transaction atomicity: debit then dispense // If dispense fails → undo() credits account back class WithdrawalCommand implements Command { public void execute() { account.debit(amount); // 1. Debit dispenser.dispense(amount); // 2. Dispense (may fail) } public void undo() { account.credit(amount); // Reversal if dispense failed logReversal(transactionId); } }
06
Hotel Booking System
BUILDER · STRATEGY · OBSERVER · CONCURRENCY
Concurrent room booking with date-range contention. Dynamic pricing (weekend/occupancy surge). Reservation waitlist with Observer notification.
Room.java — thread-safe date-range bookingJAVA
class Room { private final ReentrantLock lock = new ReentrantLock(); private final Set<LocalDate> booked = new HashSet<>(); public boolean tryBook(LocalDate in, LocalDate out) { lock.lock(); try { List<LocalDate> dates = in.datesUntil(out).collect(toList()); if (dates.stream().anyMatch(booked::contains)) return false; booked.addAll(dates); return true; } finally { lock.unlock(); } } } // Dynamic pricing strategy class DynamicPricingStrategy implements PricingStrategy { public double getPrice(Room room, LocalDate date, int occupancy) { double base = room.getBasePrice(); if (date.getDayOfWeek() == DayOfWeek.FRIDAY || date.getDayOfWeek() == DayOfWeek.SATURDAY) base *= 1.2; if (occupancy > 80) base *= 1.5; else if (occupancy > 60) base *= 1.2; return base; } }
5-step LLD interview framework
THE 5-STEP LLD FRAMEWORK — USE FOR EVERY INTERVIEW
01
CLARIFY (3 min)
Who are users? What are core use cases? Single machine or distributed? Any specific NFRs (concurrency, scale)? Don't assume — ask.
02
ENTITIES (5 min)
List 5–8 core nouns from requirements. Define key attributes and relationships. Draw a simple entity diagram. Avoid over-modelling at this stage.
03
DESIGN (15 min)
Interface first, implementation second. Identify patterns and justify WHY. Don't use a pattern unless it solves a real problem. Explain trade-offs aloud.
04
EDGE CASES (5 min)
Concurrency: which operations need thread safety? Error states: failure recovery? Validation: where is input validated? What are the invariants?
05
CODE (15 min)
Focus on the most interesting class. Show you understand the pattern — don't just write boilerplate. Verbalize trade-offs. Time-box ruthlessly.
Killer questions + strong answers
| SYSTEM | KILLER QUESTION | STRONG ANSWER |
|---|---|---|
| Chess | "How do you detect checkmate?" | Simulate every legal move for the player in check. If none escape check → checkmate. Key: simulate-check-undo via Command pattern. |
| Elevator | "Handle 1000 floors efficiently?" | TreeSet for requests (O(log n) insert/min). LOOK direction reversal. Per-elevator locking prevents cross-elevator contention. |
| Library | "Thread safety of last copy?" | synchronized(book) with double-check. ConcurrentLinkedQueue for reservation. Synchronized block is on the specific book — not the entire catalog. |
| Food Ordering | "Add new payment method?" | New class implementing PaymentHandler. Set it in the chain. Zero changes to ValidationHandler, DeliveryHandler. OCP via CoR. |
| ATM | "Network fails after debit, before dispense?" | WithdrawalCommand.undo() credits account back. Transaction ID logged for idempotent replay. Same-transaction retry is safe. |
| Hotel | "10,000 concurrent bookings for last room?" | ReentrantLock per room. tryBook() is atomic. Losers get waitlisted via reservation queue. Observer notifies when room cancels. |
Common LLD anti-patterns — avoid these in interviews
God Class
One class does everything — BookingService has 2000 lines handling payment, notifications, seat locking, pricing, emails. Violates SRP. Fix: split into focused services behind a Facade.
Anemic Domain Model
Entities are pure data bags (only getters/setters). All logic lives in service classes. Result: procedural code disguised as OOP. Fix: move behaviour to entities — Order.cancel(), Seat.lock(), Booking.getFee().
Over-Engineering
Using every design pattern you know regardless of need. A simple CRUD system with Factory + Builder + Strategy + Observer + Decorator is a red flag. Fix: use a pattern only when it solves a concrete problem.
No Interfaces
Every class references concrete types: PaymentService uses new StripeGateway() directly. Kills OCP, testability, and swappability. Fix: all dependencies injected via interfaces.
Ignoring Concurrency
"I'll add thread safety later." In interviews, the concurrency question IS the design question. Fix: identify shared mutable state upfront, choose the right primitive (atomic vs lock vs semaphore).
Exposing Internals
getBoard()[row][col] = piece — letting clients mutate internal structures. Breaks encapsulation, makes validation impossible. Fix: expose behaviour methods (makeMove, isValidMove) not raw data.
Validation Scattered Everywhere
if (seat != null && !seat.isBooked() && user != null && ...) in 12 different places. Fix: single Validator class per domain object. Or CoR where ValidationHandler is one step.
Missing Invariants
No thought given to what must always be true: "available + occupied == total", "seat has at most one booking", "balance never goes negative". Fix: state invariants explicitly; enforce in synchronized/locked sections.
// PATTERN SELECTION CHEAT SHEET
if/else on algorithm type → Strategy
Need undo/redo → Command
Object behaves differently per mode → State
One change → many notifications → Observer
Multiple handlers, unknown upfront → CoR
Simplify complex subsystem → Facade
Many optional constructor params → Builder
Limit concurrent access (N slots) → Semaphore
Incompatible interface → Adapter
Add behaviour without subclassing → Decorator
Tree structure, uniform ops → Composite
Read-heavy shared data → ReadWriteLock
01
Snake and Ladder Game
›
Design Snake and Ladder: - N players, 100-cell board, configurable snakes/ladders - Dice rolling: pluggable strategy (single die, two dice, biased die) - Special cells: snake head slides down, ladder bottom climbs up - Win condition: exactly 100 (overshoot = no move) - Multiplayer: track current player - Save/load game state (Memento) Required patterns: Factory: Dice creation Strategy: Dice rolling algorithm Observer: onPlayerMoved, onSnakeBite, onLadderClimb, onWin Command: Move (with undo for "take back" variant) Memento: Save game state to resume later Deliver: Full Java + UML + test for 4 players, 10-round game
02
Parking Lot V2 — Extensions
›
Extend the A5 Parking Lot with:
- Monthly pass holders: reserved spots, no time-based fee
- EV charging spots: AVAILABLE → CHARGING → CHARGED → AVAILABLE
- VIP spots: premium pricing, observer notification on availability
- Smart fee:
< 30 min: flat ₹20
< 2 hours: flat ₹50
> 2 hours: ₹80/hour after first 2h
- Multiple entry/exit gates (separate rate limiters per gate)
- Daily revenue report: thread-safe aggregation
Design challenge: adding EV state without breaking existing Spot hierarchy.
Show OCP — new spot type = new class, existing code unchanged.
03
Multi-Level Cache System
›
Design a three-level cache: L1: In-process LRU (1,000 items, O(1) get/put) L2: Distributed (Redis-like, 100,000 items, TTL-based eviction) L3: Database (unlimited, slowest) On get(key): Hit L1 → return immediately Miss L1, hit L2 → populate L1, return Miss L2, hit L3 → populate L2 + L1, return Miss all → return null Write policies (Strategy, pluggable): write-through: write all levels synchronously write-back: write L1 only; async flush to L2/L3 write-around: bypass cache; write directly to L3 Concurrency: ReadWriteLock per level (reads don't block each other) Invalidation: CacheInvalidationEvent via Observer pattern Test: cache hit rates, concurrency safety, write policy correctness
★
Capstone — BookMyShow (Full Track A)
›
Entities: Movie, Show, Screen, Seat, Booking, User, Theatre, Payment, Ticket Features: 1. Browse movies by city/date 2. Select show → choose seats → pay → receive ticket 3. Seat hold expires after 5 minutes if unpaid 4. Concurrent seat selection — no double booking 5. Pricing: weekday/weekend × screen type × seat type multipliers 6. Cancellation: full refund >24h, 50% refund 2–24h, none <2h 7. Notifications: booking confirmation, 2h-before show reminder All 9 patterns with justification: State: Seat (AVAILABLE/LOCKED/BOOKED/CANCELLED) Observer: Booking events, seat expiry alerts Command: BookSeat + CancelBooking with undo/refund Strategy: Pricing engine (multipliers per category) CoR: validate → price → payment → confirm → notify Facade: BookingService.bookSeats(userId, showId, seatIds) Builder: BookingRequest (optional fields: promo code, special needs) Factory: TicketFactory (standard vs IMAX vs 4DX ticket format) Concurrency: ReentrantLock per Seat + ScheduledExecutor for 5-min expiry Deliverables: 1. Complete Java implementation (every class) 2. UML class diagram with all 9 patterns annotated 3. Sequence diagram: "User books 2 IMAX seats" happy path 4. JUnit test: 20 threads try to book last 3 seats — zero double bookings
0 / 12 completedMODULE A6 · TRACK A FINAL
Can design Chess Game — move validation, undo, checkmate detection
Can design Elevator — LOOK algorithm, concurrent requests, pluggable strategy
Can design Library — reservation queue, fine calc, thread-safe last copy
Can design Food Ordering — CoR pipeline, surge pricing, order state machine
Can design ATM — PIN retry, transaction atomicity, Command undo
Can design Hotel Booking — concurrent date-range locking, dynamic pricing
Know the 5-step LLD interview framework by heart
Can recite pattern selection cheat sheet (12 patterns → triggers)
✏️ Task 1: Snake & Ladder — all 5 patterns + game state save/load
✏️ Task 2: Parking Lot V2 — EV spots, monthly pass, multi-gate
✏️ Task 3: Multi-Level Cache — 3 levels, 3 write policies, concurrent
✏️ Capstone: BookMyShow — 9 patterns, concurrency proof, UML, sequence diagram
TRACK A COMPLETE
🎉 Ready for Track B
B1 · HLD Fundamentals — CAP theorem, consistency models, availability
B2 · Databases at Scale — sharding, replication, SQL vs NoSQL
B3 · Caching — Redis, CDN, cache invalidation strategies
B4 · Message Queues — Kafka, RabbitMQ, event streaming
B5 · URL Shortener · Pastebin · TinyURL
B6–B10 · Twitter · Netflix · Uber · WhatsApp · Google Drive
B2 · Databases at Scale — sharding, replication, SQL vs NoSQL
B3 · Caching — Redis, CDN, cache invalidation strategies
B4 · Message Queues — Kafka, RabbitMQ, event streaming
B5 · URL Shortener · Pastebin · TinyURL
B6–B10 · Twitter · Netflix · Uber · WhatsApp · Google Drive