Bird
Raised Fist0

Amazon Locker Service

LLDmediumInterview freq: medium
Choose your preparation mode4 modes available
▶
Class Trace
Step 1/4
LockerManager Singleton

LockerManager uses a volatile static instance with synchronized getInstance() to ensure thread-safe lazy initialization.

🎯 Tests whether candidate knows volatile prevents JVM reordering allowing partially constructed instance to be visible, and synchronized getInstance ensures atomic check-and-set.
public class LockerManager {
    private volatile static LockerManager instance;
    private Map<String, Locker> lockers = new HashMap<>();
    private LockerManager() {}
    public static synchronized LockerManager getInstance() {
        if (instance == null) {
            instance = new LockerManager();
        }
        return instance;
    }
}
Locker composition in LockerManager

LockerManager has composition relationship with Locker, owning their lifecycle and managing assignment and release.

🎯 Tests whether candidate distinguishes composition (Locker lifecycle tied to LockerManager) from association (Package is independent).
public class LockerManager {
    private Map<String, Locker> lockers = new HashMap<>();
    public Locker assignPackage(Package pkg) {
        for (Locker locker : lockers.values()) {
            if (locker.parkPackage(pkg)) {
                return locker;
            }
        }
        return null;
    }
}
Locker synchronized methods

Locker methods parkPackage and release are synchronized to atomically check and update availability and assigned package.

🎯 Tests whether candidate understands synchronized methods ensure atomic state changes preventing race conditions on isAvailable and assignedPackage fields.
public class Locker {
    private boolean isAvailable = true;
    private Package assignedPackage;
    public synchronized boolean parkPackage(Package pkg) {
        if (!isAvailable) return false;
        assignedPackage = pkg;
        isAvailable = false;
        return true;
    }
    public synchronized boolean release() {
        if (isAvailable) return false;
        assignedPackage = null;
        isAvailable = true;
        return true;
    }
}
OTPGenerator Factory pattern

OTPGenerator is a Factory that creates OTP instances, encapsulating OTP creation logic and allowing extensibility.

🎯 Tests whether candidate recognizes Factory pattern realization and how it supports Open-Closed Principle by decoupling OTP creation from usage.
public class OTPGenerator {
    public OTP generateOTP() {
        String code = generateRandomCode();
        long expiry = System.currentTimeMillis() + 5 * 60 * 1000;
        return new OTP(code, expiry);
    }
    private String generateRandomCode() {
        // implementation omitted
        return "123456";
    }
}
📐
Class Diagram
Class Diagram
       +----------------+
       | LockerManager  | <<Singleton>>
       +----------------+
       | - volatile static instance : LockerMgr
       | - Map<String, Locker> lockers
       +----------------+
       | + public static LockerManager getInstance() [sync]
       | + public Locker assignPackage(Package pkg)
       | + public boolean releaseLocker(String lockerId)
       +----------------+
              │ ◆ composition
              │
       +----------------+
       |     Locker     |
       +----------------+
       | - String id
       | - boolean isAvailable
       | - Package assignedPackage
       +----------------+
       | + public synchronized boolean parkPackage(Package pkg) [sync]
       | + public synchronized boolean release() [sync]
       +----------------+
              │ ─ ─ ─► realization
              │
       +----------------+
       |    Package     |
       +----------------+
       | - String packageId
       | - String recipient
       +----------------+
       +----------------+
              │ ─ ─ ─► realization
              │
       +----------------+
       |  OTPGenerator  | <<Factory>>
       +----------------+
       | + public OTP generateOTP()
       +----------------+
              │ ─ ─ ─► realization
              │
       +----------------+
       |      OTP       |
       +----------------+
       | - String code
       | - long expiryTimestamp
       +----------------+
       | + public boolean isExpired()
       +----------------+

This class diagram illustrates four key classes in the Amazon Locker Service design. LockerManager is a Singleton with a volatile instance and synchronized getInstance() method to ensure thread-safe lazy initialization, preventing partially constructed instances from being visible to other threads. It composes Locker objects, owning their lifecycle and managing package assignments. Locker methods parkPackage and release are synchronized to atomically update availability and assigned package state, preventing race conditions. OTPGenerator implements the Factory pattern, encapsulating OTP creation and supporting Open-Closed Principle by decoupling OTP instantiation from usage. The diagram uses composition for LockerManager to Locker, association for LockerManager to Package, and realization for OTPGenerator to OTP, clearly showing lifecycle ownership and design patterns.

Primary Focus

✓ Composition vs Association lifecycle + Singleton volatile + Factory realization

Practice

(1/5)
1. You are designing a Vehicle abstraction for an adapter pattern implementation. Should Vehicle be an abstract class or an interface, and why?
easy
A. Abstract class, because it allows sharing state and behavior among all vehicles.
B. Abstract class, because interfaces cannot have any methods in Java.
C. Interface, because it allows storing instance variables for all vehicles.
D. Interface, because it defines only behavior contracts without state, enabling multiple inheritance.

Solution

  1. Step 1: Understand Vehicle abstraction needs

    Vehicle defines behavior (methods) but should not hold state to allow flexible adapter implementations and multiple inheritance.
  2. Step 2: Evaluate Java constructs

    Interfaces define behavior contracts without state, allowing multiple inheritance. Abstract classes can hold state but limit inheritance.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Interface defines behavior only, enabling flexible adapters [check]
Hint: Interface for behavior only, abstract class for shared state [check]
Common Mistakes:
2. In a multi-threaded parking system using the Decorator pattern, the parkVehicle() method checks if a spot is available and then marks it occupied. Without synchronization, which exact thread interleaving causes double-booking?
medium
A. Thread 1 checks spot available -> true, context switch; Thread 2 checks spot available -> true; both mark spot occupied concurrently.
B. Thread 1 marks spot occupied, Thread 2 waits and then parks safely.
C. Thread 1 parks vehicle, Thread 2 reads spot status after parking completes.
D. Thread 1 and Thread 2 both wait on a lock, preventing double-booking.

Solution

  1. Step 1: Identify the check-then-act race condition

    Without synchronization, Thread 1 reads spot as available (true) but before marking it occupied, context switches.
  2. Step 2: Trace Thread 2's actions

    Thread 2 also reads spot as available (true) and proceeds to mark it occupied. Both threads think the spot is free and park vehicles, causing double-booking.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Check-then-act without sync allows both threads to park simultaneously [check]
Hint: Check-then-act gap causes double-booking without sync [check]
Common Mistakes:
3. In a multi-threaded Chess game server, without synchronizing the makeMove() method, which exact sequence of thread interleaving causes two players to move simultaneously, violating turn order?
medium
A. Thread 1 reads current player as White, moves piece; Thread 2 reads current player as Black, moves piece simultaneously.
B. Thread 1 checks if it's White's turn -> true, context switch; Thread 2 checks if it's White's turn -> true; both proceed to move.
C. Thread 1 locks board, moves piece; Thread 2 waits but proceeds after unlock.
D. Thread 1 updates board state; Thread 2 reads stale board state but waits for turn.

Solution

  1. Step 1: Identify the check-then-act race condition

    Both threads read the turn state before either updates it, causing both to believe it's their turn.
  2. Step 2: Trace thread interleaving

    Thread 1 checks turn -> true, context switch before move; Thread 2 checks turn -> true, both move simultaneously, violating turn order.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Check-then-act gap allows double move without synchronization [check]
Hint: Check turn then act without lock -> race condition [check]
Common Mistakes:
4. To support ElectricCar bidders requiring ChargingSpot reservations in the auction system, what is the minimum change to the current Java design to maintain extensibility without modifying existing classes?
hard
A. Modify Vehicle base class to include charging logic and add ChargingSpot as a subclass of Spot.
B. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally.
C. Create a new ElectricCarChargingManager class that extends AuctionManager and handles charging spots internally.
D. Add charging logic directly inside existing Bid and Spot classes to handle electric cars.

Solution

  1. Step 1: Identify extensibility without modification

    Adding new enum values and subclasses extends functionality without changing existing class code.
  2. Step 2: Update SpotCompatibility map externally to maintain compatibility rules without modifying existing classes.

  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Extend enums + subclass + external map update -> minimal change [check]
Hint: Extend enums + subclass + external map update -> minimal change [check]
Common Mistakes:
5. ElectricCar requires ChargingSpots in the parking lot system. What is the minimum change to support this without modifying existing classes?
hard
A. Add ELECTRIC_CAR to VehicleType, CHARGING to SpotType, create ElectricCar extending Vehicle, and update SpotCompatibility.COMPATIBILITY_MAP accordingly.
B. Modify Vehicle class to include a chargingRequired flag and update all spot checks.
C. Create a new ChargingSpot class and modify ParkingLot to handle it specially.
D. Add a new interface Chargeable and make ElectricCar implement it, changing existing spot logic.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and a subclass extends functionality without changing existing class code, respecting OCP.
  2. Step 2: Evaluate options

    Modify Vehicle class to include a chargingRequired flag and update all spot checks. modifies Vehicle, violating OCP. Create a new ChargingSpot class and modify ParkingLot to handle it specially. requires modifying ParkingLot, violating minimal change. Add a new interface Chargeable and make ElectricCar implement it, changing existing spot logic. adds interface but requires changing spot logic, violating minimal change.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New enums + subclass + compatibility map update -> minimal change [check]
Hint: Add enums + subclass + compatibility map, 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