Pro Tip
The absolute secret to passing LLD (Low-Level Design): The Golden Trio. Most interview problems (Parking Lot, Elevator, TicTacToe, Payment Gateway) can be solved robustly using a combination of the Factory, Strategy, and Observer patterns alongside solid Object Composition.
The Golden Trio Applied: A Parking Lot
Let's build the crucial components of a Parking Lot design using the Golden Trio. A Parking Lot needs to dynamically assign parking spots based on different strategies (Nearest to entrance, VIP first, Random). It also needs to construct different types of tickets (Factory).
1. The Strategy Pattern (Dynamic Algorithms)
Instead of hardcoding `assignSpot` with giant if/else blocks, we abstract the algorithm.
typescript
// The abstraction representing the algorithm
interface IParkingStrategy {
findSpot(spots: ParkingSpot[], vehicle: Vehicle): ParkingSpot | null;
}
// Concrete Strategy A
class NearestToEntranceStrategy implements IParkingStrategy {
findSpot(spots: ParkingSpot[], vehicle: Vehicle): ParkingSpot | null {
// Logic to find spot with lowest distance metric that fits vehicle type
return spots.find(s => s.isFree && s.size >= vehicle.size) || null;
}
}
// Concrete Strategy B
class VIPFirstStrategy implements IParkingStrategy {
findSpot(spots: ParkingSpot[], vehicle: Vehicle): ParkingSpot | null {
// Look for VIP spots first, then fallback
return fallbackLogic();
}
}2. The Factory Pattern (Scalable Instantiation)
When a car enters, we issue a Ticket. We use a Factory to encapsulate the complex initialization logic.
typescript
class TicketFactory {
private static idCounter = 1;
public static generateTicket(vehicle: Vehicle, spot: ParkingSpot): Ticket {
const ticketId = "TKT-" + this.idCounter++;
const entryTime = new Date();
// Factory encapsulates complexity
spot.isFree = false;
return new Ticket(ticketId, vehicle, spot, entryTime);
}
}3. Composition (Entry Gate Assembly)
Now we bind it all together at the EntryGate.
typescript
class EntryGate {
private gateId: string;
private parkingStrategy: IParkingStrategy; // Dependency Injection
constructor(id: string, strategy: IParkingStrategy) {
this.gateId = id;
this.parkingStrategy = strategy;
}
public processVehicleEntry(vehicle: Vehicle, allSpots: ParkingSpot[]): Ticket | null {
// 1. Ask Strategy for a spot
const spot = this.parkingStrategy.findSpot(allSpots, vehicle);
if (!spot) {
console.log("No spots available!");
return null;
}
// 2. Ask Factory for a Ticket
const ticket = TicketFactory.generateTicket(vehicle, spot);
return ticket;
}
}If the interviewer says: "We now need to change the spot assignment algorithm during rush hour." Because you used the **Strategy Pattern**, you just inject a new `RushHourStrategy` into the `EntryGate`, completely satisfying the **Open-Closed Principle (OCP)**!
Take the Phase Interview
Solidify your knowledge. We will ask you 5 random highly-technical questions from the Phase 3: Design Patterns in Action bucket. A Staff Engineer AI will strictly evaluate your answers.