Bird
Raised Fist0

Why Design Patterns Exist and When Not to Use Them

LLDeasyInterview freq: medium
Choose your preparation mode4 modes available
▶
Class Trace
Step 1/4
Vehicle abstract class

Vehicle is an abstract class holding shared state like licensePlate and vehicleType

🎯 Tests whether candidate knows abstract class is correct because Vehicle holds instance state which interfaces cannot hold in Java
public abstract class Vehicle {
    protected String licensePlate;
    protected String vehicleType;
    public String getLicensePlate() { return licensePlate; }
    public String getVehicleType() { return vehicleType; }
}
ParkingLot Singleton with volatile

ParkingLot is a Singleton with volatile instance and synchronized getInstance() to ensure safe lazy init

🎯 Tests whether candidate states volatile prevents JVM reordering and synchronized ensures atomic check-and-set for thread-safe Singleton
public class ParkingLot {
    private static volatile ParkingLot instance;
    private ParkingLot() { }
    public static synchronized ParkingLot getInstance() {
        if (instance == null) {
            instance = new ParkingLot();
        }
        return instance;
    }
}
Composition relationship ParkingLot ◆ Vehicle

ParkingLot composes Vehicles, owning their lifecycle strongly (composition)

🎯 Tests whether candidate distinguishes composition (ParkingLot owns Vehicles) from association (independent lifecycle)
public class ParkingLot {
    private List<Vehicle> parkedVehicles = new ArrayList<>();
    public synchronized boolean parkVehicle(Vehicle v) {
        if (parkedVehicles.contains(v)) return false;
        parkedVehicles.add(v);
        return true;
    }
}
PricingStrategy interface and FlatRatePricing realization

PricingStrategy is an interface defining calculateFee, implemented by FlatRatePricing

🎯 Tests whether candidate understands interface defines behavior contract without state and realization enforces OCP for extensibility
public interface PricingStrategy {
    double calculateFee(Vehicle v);
}
public class FlatRatePricing implements PricingStrategy {
    public double calculateFee(Vehicle v) {
        return 10.0; // flat rate
    }
}
📐
Class Diagram
Class Diagram
       +----------------------+
       | <<Abstract>>         |
       | Vehicle              |
       |----------------------|
       | - licensePlate: String|
       | - vehicleType: String |
       |----------------------|
       | + getLicensePlate():  |
       |   String              |
       | + getVehicleType():   |
       |   String              |
       +----------------------+
               │ extends
       +----------------------+
       | Car                  |
       |----------------------|
       |                      |
       |----------------------|
       | + getVehicleType():  |
       |   String             |
       +----------------------+
               │ association
       +----------------------+
       | <<Singleton>>        |
       | ParkingLot           |
       |----------------------|
       | - instance: volatile |
       |   ParkingLot         |
       |----------------------|
       | + getInstance():     |
       |   ParkingLot [sync]  |
       | + parkVehicle(v:     |
       |   Vehicle): boolean  |
       +----------------------+
               │ composition
       +----------------------+
       | <<Interface>>        |
       | PricingStrategy      |
       |----------------------|
       | + calculateFee(v:    |
       |   Vehicle): double   |
       +----------------------+
               ─ ─ ─► realization
       +----------------------+
       | FlatRatePricing      |
       |----------------------|
       | + calculateFee(v:    |
       |   Vehicle): double   |
       +----------------------+

This diagram illustrates four key Java OOP design decisions. First, Vehicle is an abstract class because it holds shared instance state like licensePlate and vehicleType, which interfaces cannot hold in Java. Second, ParkingLot is implemented as a thread-safe Singleton using a volatile instance field and synchronized getInstance() method to prevent JVM reordering and ensure safe lazy initialization. Third, ParkingLot composes Vehicles, owning their lifecycle strongly, which enforces composition over association and clarifies lifecycle ownership. Fourth, PricingStrategy is an interface defining a behavior contract without state, realized by FlatRatePricing, demonstrating the Strategy pattern and Open-Closed Principle for extensibility without modifying existing code. These decisions highlight why abstract classes beat interfaces when state is needed, why volatile and synchronized are essential for Singleton correctness, and how composition and interface realization enforce SOLID principles in Java.

Primary Focus

✓ Abstract class state vs interface behavior + Composition lifecycle + Strategy pattern realization + Singleton volatile

Practice

(1/5)
1. In a Java class hierarchy, a base class defines a final method that calls several abstract methods which subclasses must implement. Which design pattern is this an example of?
easy
A. Template Method Pattern, because the base class defines the algorithm skeleton and subclasses fill in steps.
B. Strategy Pattern, because subclasses provide interchangeable algorithms.
C. Factory Method Pattern, because the base class creates objects via subclass overrides.
D. Decorator Pattern, because behavior is added dynamically by subclasses.

Solution

  1. Step 1: Identify the role of the final method

    The base class's final method defines the fixed algorithm skeleton, preventing subclasses from changing the overall flow.
  2. Step 2: Recognize abstract methods as extension points

    Subclasses implement abstract methods to fill in specific steps, matching the Template Method pattern's intent.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Base class controls algorithm flow; subclasses customize steps [check]
Hint: Final method fixes flow; subclasses fill steps [check]
Common Mistakes:
2. In a UML class diagram, should Vehicle be modeled as an abstract class or an interface if it has state like speed and behavior like accelerate()? Why?
easy
A. Interface, because it allows multiple inheritance and defines behavior without state.
B. Abstract class, because it can hold shared state and provide default behavior implementations.
C. Interface, because state can be stored externally and behavior defined via default methods.
D. Abstract class, because interfaces cannot declare methods with parameters.

Solution

  1. Step 1: Analyze state and behavior requirements

    Vehicle has state (speed) and behavior (accelerate()), so it needs a construct that supports instance variables and method implementations.
  2. Step 2: Evaluate abstract class vs interface

    Abstract classes can hold state and provide default behavior; interfaces cannot hold instance state (only constants) and default methods can't maintain state.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    State + behavior with shared code -> abstract class [check]
Hint: Stateful base class -> abstract class, not interface [check]
Common Mistakes:
3. In a concurrent Snake and Ladder game server, if the movePlayer() method is not synchronized, which exact thread interleaving can cause two players to occupy the same board position simultaneously?
medium
A. Thread 1 and Thread 2 both wait on a condition variable, preventing race.
B. Thread 1 reads player position, Thread 2 reads player position, both update position without conflict.
C. Thread 1 updates position, Thread 2 waits for lock, then updates position safely.
D. Thread 1 checks if position is free -> true, context switch, Thread 2 checks -> true, both move to same position.

Solution

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

    Without synchronization, both threads check if a position is free before moving.
  2. Step 2: Trace interleaving

    Thread 1 checks position free -> true, context switch before moving; Thread 2 also checks -> true and moves; both occupy same position.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Unsynchronized check-then-act causes double occupancy [check]
Hint: Check free -> context switch -> both move -> race [check]
Common Mistakes:
4. The Restaurant Management System needs to support ElectricCar vehicles that require ChargingSpots. What is the minimum change to the current Java design to add this feature without modifying existing classes?
hard
A. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally.
B. Modify Vehicle class to include a boolean isElectric field and add charging logic inside existing methods.
C. Create a new ChargingSpot class extending Spot and modify TableManager to handle charging spots explicitly.
D. Add charging logic inside the existing Spot class and modify all subclasses to support electric vehicles.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and subclasses without changing existing classes respects OCP and avoids class explosion.
  2. Step 2: Update compatibility externally

    Updating SpotCompatibility map outside existing classes allows new vehicle and spot types to integrate without modifying existing code.
  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 -> minimal change [check]
Common Mistakes:
5. ElectricCar requires ChargingSpots in the parking system using Prototype pattern. What is the minimum change to support this without modifying existing classes?
hard
A. Modify Vehicle base class to include charging logic and add ChargingSpot as a subclass of Spot
B. Add charging logic inside Vehicle clone() and modify SpotCompatibility map inside existing classes
C. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally
D. Create a god-class that handles both ElectricCar and ChargingSpot logic to avoid modifying existing classes

Solution

  1. Step 1: Identify extensibility requirements

    Adding ElectricCar and ChargingSpot must avoid modifying existing classes to respect OCP.
  2. Step 2: Evaluate options for minimal invasive change

    Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally adds new enum values and subclasses externally, updating compatibility map without changing existing code. Options B and C modify base classes, violating OCP. Create a god-class that handles both ElectricCar and ChargingSpot logic to avoid modifying existing classes creates god-class, violating SRP and maintainability.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    New enums + subclass + external map update -> minimal change, OCP respected [check]
Hint: New enums + subclass + external map -> minimal invasive 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