Bird
Raised Fist0

Elevator System - Scheduling Algorithm, Multiple Lifts, Floor Queue

LLDmediumInterview freq: high
Choose your preparation mode4 modes available
▶
Class Trace
Step 1/4
ElevatorController composition

ElevatorController composes multiple Elevator instances, owning their lifecycle and coordinating them.

🎯 Tests understanding of composition in Java where ElevatorController controls Elevator lifecycle and uses synchronized dispatchRequest to avoid race conditions.
public class ElevatorController {
    private final List<Elevator> elevators = new ArrayList<>();
    private final Scheduler scheduler;
    public ElevatorController(Scheduler scheduler) {
        this.scheduler = scheduler;
    }
    public synchronized void dispatchRequest(FloorRequest req) {
        Elevator e = scheduler.schedule(elevators.toArray(new Elevator[0]), req);
        if (e != null) {
            e.moveToFloor(req.getFloorNumber());
        }
    }
    public void addElevator(Elevator e) { elevators.add(e); }
}
Scheduler interface and SimpleScheduler realization

Scheduler is an interface to allow different scheduling algorithms; SimpleScheduler implements it for basic scheduling logic.

🎯 Tests OCP (Open-Closed Principle) by using interface for Scheduler to allow extensibility without modifying ElevatorController.
public interface Scheduler {
    Elevator schedule(Elevator[] elevators, FloorRequest request);
}
public class SimpleScheduler implements Scheduler {
    @Override
    public Elevator schedule(Elevator[] elevators, FloorRequest request) {
        // Simple logic to pick first available elevator
        for (Elevator e : elevators) {
            if (e.isAvailable()) return e;
        }
        return null;
    }
}
Elevator class with volatile isAvailable and synchronized moveToFloor

Elevator uses volatile boolean isAvailable to ensure visibility across threads and synchronized moveToFloor to atomically update state.

🎯 Tests Java concurrency knowledge: volatile ensures visibility of isAvailable flag, synchronized moveToFloor prevents race conditions during state changes.
public class Elevator {
    private int id;
    private int currentFloor;
    private volatile boolean isAvailable = true;
    public synchronized void moveToFloor(int floor) {
        isAvailable = false;
        // simulate movement
        currentFloor = floor;
        isAvailable = true;
    }
    public boolean isAvailable() { return isAvailable; }
}
Singleton pattern for ElevatorController

ElevatorController is a singleton to ensure a single point of coordination; volatile instance prevents half-constructed object visibility.

🎯 Tests correct Singleton implementation in Java with volatile instance and double-checked locking to avoid concurrency bugs.
public class ElevatorController {
    private static volatile ElevatorController instance;
    private ElevatorController(Scheduler scheduler) {
        this.scheduler = scheduler;
    }
    public static ElevatorController getInstance(Scheduler scheduler) {
        if (instance == null) {
            synchronized (ElevatorController.class) {
                if (instance == null) {
                    instance = new ElevatorController(scheduler);
                }
            }
        }
        return instance;
    }
    // rest of class omitted for brevity
}
📐
Class Diagram
Class Diagram
       +----------------------+
       | <<Singleton>>        |
       | ElevatorController   |
       +----------------------+
       | - elevators: List<Elev> |
       | - scheduler: Scheduler |
       +----------------------+
       | + dispatchReq(FloorRequest) [sync] |
       | + addElev(Elevator)               |
       +----------------------+
              ◆ composition
                 │
                 │
       +----------------------+
       | <<Interface>>        |
       | Scheduler            |
       +----------------------+
       | + schedule(Elevator[], FloorRequest): Elevator |
       +----------------------+
                 ▲ realization
                 │
       +----------------------+
       | SimpleScheduler      |
       +----------------------+
       | + schedule(...)      |
       +----------------------+
              ▲ association
              │
       +----------------------+
       | Elevator             |
       +----------------------+
       | - id: int            |
       | - currentFloor: int  |
       | - isAvailable: volatile boolean |
       +----------------------+
       | + moveToFloor(int) [sync] |
       | + isAvailable()           |
       +----------------------+

This Elevator System design uses ElevatorController as a Singleton to ensure a single coordination point, employing volatile on the instance to prevent visibility of a partially constructed object. ElevatorController composes multiple Elevator objects, owning their lifecycle, and uses synchronized dispatchRequest to safely assign requests. Scheduler is an interface to enable extensible scheduling algorithms, following the Open-Closed Principle, with SimpleScheduler as a basic implementation. Elevator uses volatile isAvailable to guarantee visibility of availability state across threads and synchronized moveToFloor to atomically update its state, preventing race conditions during movement.

Primary Focus

✓ Composition vs Association lifecycle + Scheduler as Strategy + Singleton volatile

Practice

(1/5)
1. In the Online Shopping Cart system, the Cart class has a private constructor and a static synchronized getInstance() method. Which design pattern is applied here, and why is this the correct use case?
easy
A. Factory pattern, because it controls object creation centrally.
B. Singleton pattern, to ensure only one Cart instance exists per user session.
C. Builder pattern, to construct Cart objects step-by-step.
D. Prototype pattern, to clone Cart instances efficiently.

Solution

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

    The private constructor prevents external instantiation, and the static synchronized getInstance() method controls instance creation, which matches the Singleton pattern.
  2. Step 2: Reason why Singleton fits Cart

    Ensuring only one Cart instance per user session avoids inconsistent states and duplicate carts, which is the intended use case here.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Private constructor + synchronized getInstance() -> Singleton pattern [check]
Hint: Private constructor + static getInstance() -> Singleton [check]
Common Mistakes:
2. You want to add a WeekendFeeStrategy to the rate limiter's fee calculation without modifying existing classes. Which SOLID principle applies and what is the minimum change?
medium
A. Add weekend flag to RateLimiter and use if-else inside existing fee method
B. Create new WeekendFeeStrategy implementing FeeStrategy interface; inject it via constructor (OCP and DIP enforced)
C. Modify RateLimiter class to add weekend fee logic directly, violating OCP
D. Create WeekendFeeStrategy but modify existing FeeStrategy implementations to handle weekend

Solution

  1. Step 1: Identify SOLID principle for adding new fee logic

    Open-Closed Principle (OCP) requires adding new behavior without modifying existing code.
  2. Step 2: Evaluate options for minimal change respecting OCP and DIP

    Add weekend flag to RateLimiter and use if-else inside existing fee method adds weekend flag and if-else inside existing method, violating OCP by modifying existing class. Create new WeekendFeeStrategy implementing FeeStrategy interface; inject it via constructor (OCP and DIP enforced) respects OCP and DIP by adding new class and injecting it.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Minimal change but violates OCP by modifying existing class [check]
Hint: OCP: add new class, not modify existing code [check]
Common Mistakes:
3. The Wallet System currently calculates fees with a FeeStrategy interface. To add a WeekendFeeStrategy without modifying existing classes, which SOLID principle is being applied and what is the minimum required change?
medium
A. Open/Closed Principle: create WeekendFeeStrategy implementing FeeStrategy; no existing class changes.
B. Dependency Inversion Principle: inject WeekendFeeStrategy into Account class by modifying Account.
C. Single Responsibility Principle: modify FeeStrategy to handle weekends explicitly.
D. Liskov Substitution Principle: override FeeStrategy methods in WeekendFeeStrategy and modify Transaction.

Solution

  1. Step 1: Identify the SOLID principle for extensibility

    Open/Closed Principle (OCP) states software entities should be open for extension but closed for modification.
  2. Step 2: Apply OCP to fee calculation

    Adding WeekendFeeStrategy as a new class implementing FeeStrategy extends behavior without modifying existing classes, preserving OCP.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New FeeStrategy implementation -> no existing class changes -> OCP [check]
Hint: Add new strategy class, no existing code change -> OCP [check]
Common Mistakes:
4. Adding a WeekendFeeStrategy to the parking lot pricing requires which minimum change to comply with SOLID principles?
medium
A. Modify the existing FeeCalculator class to add weekend logic with an if-else block.
B. Add a boolean isWeekend flag to Vehicle and change pricing logic accordingly.
C. Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes.
D. Combine all fee strategies into one large class with multiple methods for each pricing rule.

Solution

  1. Step 1: Identify the SOLID principle involved

    The Open-Closed Principle (OCP) requires that classes be open for extension but closed for modification.
  2. Step 2: Evaluate options against OCP

    Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes. respects OCP by adding a new strategy class without modifying existing code. Add a boolean isWeekend flag to Vehicle and change pricing logic accordingly. violates OCP by modifying Vehicle state, which is unrelated to pricing and causes tight coupling.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    New strategy class -> OCP-compliant extension [check]
Hint: OCP: add new class, don't modify existing ones [check]
Common Mistakes:
5. The system must support ElectricCar vehicles needing ChargingSpot parking. What is the minimum change to the current design to support this without modifying existing classes?
hard
A. Add a boolean isElectric flag to Vehicle and ParkingSpot classes and update all compatibility checks.
B. Modify existing Vehicle and ParkingSpot classes to add electric-specific fields and logic.
C. Create a new ElectricVehicleManager class that handles electric cars separately, duplicating some logic.
D. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and subclassing allows extension without changing existing class code, respecting OCP.
  2. Step 2: Update compatibility externally

    Updating SpotCompatibility map outside existing classes avoids modifying their code, enabling new vehicle-spot matching.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Extend enums + subclass + external map update -> no existing class changes [check]
Hint: Extend enums + subclass + external map -> no existing class changes [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