Bird
Raised Fist0

How to Approach Any LLD Problem in 45 Minutes - Step-by-Step Framework

LLDmediumInterview freq: high
Choose your preparation mode4 modes available
▶
Class Trace
Step 1/4
Requirement and Entity inheritance

Requirement is an abstract class extended by Entity to share common state like description and priority which interfaces cannot hold in Java.

🎯 Tests whether candidate knows abstract class is chosen over interface because Requirement holds instance state (description, priority) that interfaces cannot hold in Java.
public abstract class Requirement {
    protected String description;
    protected int priority;
    public abstract boolean validate();
    public String getDetails() { return description + priority; }
}
public class Entity extends Requirement {
    private String name;
    private List<String> attributes = new ArrayList<>();
    public String getName() { return name; }
    public void addAttr(String attr) { attributes.add(attr); }
    @Override
    public boolean validate() { return description != null; }
}
Composition between Entity and Relationship

Entity composes Relationship, meaning Relationship lifecycle is owned by Entity and cannot exist independently.

🎯 Tests whether candidate understands composition relationship and lifecycle ownership in Java, ensuring Relationship is created and destroyed with Entity.
public class Entity extends Requirement {
    private List<Relationship> relationships = new ArrayList<>();
    public void addRelationship(Relationship r) { relationships.add(r); }
}
public class Relationship {
    private String type;
    private Entity source;
    private Entity target;
    public String getType() { return type; }
    public Entity getSource() { return source; }
    public Entity getTarget() { return target; }
}
ConcurrencyScenario aggregation with CodeSkeleton

ConcurrencyScenario aggregates CodeSkeleton, meaning CodeSkeleton can exist independently and is shared for code examples.

🎯 Tests whether candidate distinguishes aggregation from composition and understands shared lifecycle in Java aggregation.
public class ConcurrencyScenario {
    private String description;
    private List<String> threadSteps;
    private CodeSkeleton codeSkeleton;
    public void simulate() { /* simulate thread interleaving */ }
    public void analyze() { /* analyze race conditions */ }
    public void setCodeSkeleton(CodeSkeleton cs) { this.codeSkeleton = cs; }
}
public class CodeSkeleton {
    private List<String> codeLines = new ArrayList<>();
    public void addLine(String line) { codeLines.add(line); }
    public List<String> getCode() { return codeLines; }
}
Use of volatile in Singleton pattern (implied in framework)

Singleton pattern uses volatile instance field to prevent JVM reordering and ensure fully constructed instance is visible to all threads.

🎯 Tests whether candidate knows volatile keyword prevents half-initialized Singleton instance visibility due to JVM instruction reordering.
public class FrameworkSingleton {
    private static volatile FrameworkSingleton instance;
    private FrameworkSingleton() { }
    public static FrameworkSingleton getInstance() {
        if (instance == null) {
            synchronized(FrameworkSingleton.class) {
                if (instance == null) {
                    instance = new FrameworkSingleton();
                }
            }
        }
        return instance;
    }
}
📐
Class Diagram
Class Diagram
       +----------------+
       | <<Abstract>>   |
       | Requirement    |
       +----------------+
       | - description  |
       | - priority     |
       +----------------+
       | + validate()   |
       | + getDetails() |
       +----------------+
              │
              │ extends
       +----------------+
       | Entity         |
       +----------------+
       | - name         |
       | - attributes   |
       +----------------+
       | + getName()    |
       | + addAttr()    |
       +----------------+
              │
              │ composition
       +----------------+
       | Relationship   |
       +----------------+
       | - type         |
       | - source       |
       | - target       |
       +----------------+
       | + getType()    |
       | + getSource()  |
       +----------------+
              │
              │ association
       +----------------+
       | Concurrency    |
       | Scenario       |
       +----------------+
       | - description  |
       | - threadSteps  |
       +----------------+
       | + simulate()   |
       | + analyze()    |
       +----------------+
              │
              │ aggregation
       +----------------+
       | CodeSkeleton   |
       +----------------+
       | - codeLines[]  |
       +----------------+
       | + getCode()    |
       | + addLine()    |
       +----------------+

This class diagram illustrates key design decisions in the LLD framework. Requirement is an abstract class to hold shared state like description and priority, which interfaces cannot hold in Java, enforcing the use of abstract classes for stateful entities. Entity composes Relationship, showing composition lifecycle ownership where Relationships cannot exist independently, enforcing strong containment. ConcurrencyScenario aggregates CodeSkeleton, demonstrating aggregation where CodeSkeleton can exist independently and be shared, reflecting flexible lifecycle management. The Singleton pattern uses a volatile instance field to prevent JVM instruction reordering, ensuring thread-safe lazy initialization. These decisions reflect SOLID principles, Java-specific concurrency mechanisms, and lifecycle ownership critical for extensible and thread-safe design.

Primary Focus

✓ Abstract class vs Interface state + Composition lifecycle + Template Method pattern + volatile Singleton

Practice

(1/5)
1. A class CarBuilder constructs a Car object step-by-step using methods like setEngine(), setWheels(), and finally build(). The Car constructor is private. Which design pattern is applied here and why is it the correct choice?
easy
A. Builder pattern, because it separates complex object construction from its representation, allowing stepwise creation.
B. Factory Method pattern, because it creates objects through inheritance and subclasses.
C. Prototype pattern, because it clones existing objects to create new ones efficiently.
D. Singleton pattern, because it ensures only one instance of Car exists.

Solution

  1. Step 1: Identify the construction process

    The class uses multiple setter methods to configure parts of the object before finalizing with build(), indicating stepwise construction.
  2. Step 2: Match pattern intent

    Builder pattern separates construction from representation, ideal for complex objects with many optional parts. Factory Method uses inheritance, Prototype clones objects, Singleton restricts instance count.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Stepwise object creation with private constructor -> Builder pattern [check]
Hint: Stepwise construction with private constructor -> Builder pattern [check]
Common Mistakes:
2. A class has a private constructor and a static synchronized getInstance() method that returns the single instance. Which pattern is applied and why is this the CORRECT use case?
easy
A. Singleton pattern, because it ensures only one instance with thread-safe lazy initialization.
B. Factory Method pattern, because it controls object creation through subclassing.
C. Builder pattern, because it separates construction from representation.
D. Prototype pattern, because it clones existing instances to avoid new creation.

Solution

  1. Step 1: Identify the pattern from constructor and method

    The private constructor prevents external instantiation, and the static synchronized getInstance() method ensures a single instance is created lazily and safely in multithreaded contexts.
  2. Step 2: Eliminate other creational patterns

    Factory Method uses subclassing, Builder separates construction steps, and Prototype clones objects; none match the private constructor plus static synchronized method pattern.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Private constructor + synchronized static getInstance() -> Singleton pattern [check]
Hint: Private constructor + synchronized static method -> Singleton [check]
Common Mistakes:
3. In a multi-threaded parking lot system using Abstract Factory to create vehicles and spots, if parkVehicle() is not synchronized, which exact thread interleaving causes double-booking of the same spot?
medium
A. Thread 1 parks vehicle, Thread 2 parks vehicle after Thread 1 finishes.
B. Thread 1 checks spot availability -> true, context switch; Thread 2 checks spot availability -> true; both park simultaneously.
C. Thread 1 parks vehicle, Thread 2 waits for Thread 1 to release lock before parking.
D. Thread 1 and Thread 2 both fail to find any available spots and abort.

Solution

  1. Step 1: Identify race condition in parkVehicle()

    Without synchronization, two threads can both check spot availability before either marks it occupied.
  2. Step 2: Trace exact interleaving

    Thread 1 calls isAvailable() -> true, context switch before marking occupied; Thread 2 calls isAvailable() -> true; both proceed to park, causing double-booking.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Check-then-act gap without synchronization causes double-booking [check]
Hint: Check-then-act gap -> both see available, both park [check]
Common Mistakes:
4. In a multi-threaded parking lot system, if parkVehicle() is not synchronized, which exact sequence of Thread 1 and Thread 2 calls causes double-booking of the same spot?
medium
A. Thread 1 checks spot availability -> true, context switch; Thread 2 checks spot availability -> true; both park simultaneously.
B. Thread 1 parks vehicle, Thread 2 waits for Thread 1 to finish, then parks vehicle.
C. Thread 1 parks vehicle, Thread 2 parks vehicle immediately after without checking availability.
D. Thread 1 releases spot, Thread 2 parks vehicle before Thread 1 finishes updating status.

Solution

  1. Step 1: Identify race condition

    Without synchronization, both threads can read spot availability as true before either marks it occupied.
  2. Step 2: Trace exact interleaving

    Thread 1: isAvailable() -> true, context switch; Thread 2: isAvailable() -> true; both proceed to park, causing double-booking.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Check-then-act gap without synchronization -> double-booking [check]
Hint: Check availability then park must be atomic to avoid double-booking [check]
Common Mistakes:
5. Electric cars require charging spots in the parking module. What is the minimum change to the current Java design to support ElectricCar and ChargingSpot without modifying existing classes?
hard
A. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType, create ElectricCar subclass, and update compatibility map externally.
B. Modify Vehicle class to add an isElectric flag and update spot compatibility logic inside existing classes.
C. Create a new ElectricVehicle interface and make ElectricCar implement it, modifying Spot to check for this interface.
D. Add charging logic inside existing ParkingLot class and extend Spot with charging capability.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and subclasses allows extension without changing existing class code.
  2. Step 2: Update compatibility map externally to maintain open-closed principle and avoid class explosion.

    Options B, C, and D require modifying existing classes, violating OCP or causing tight coupling.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New enums + subclass + external compatibility update -> minimal change [check]
Hint: Add enums + subclass + external map update, no existing class change [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard