Bird
Raised Fist0

State Pattern - Modeling Finite State Machines in ATM, Elevator, Vending Machine

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

State is an abstract class holding a reference to Context and defining common behavior methods.

🎯 Tests whether candidate knows abstract class is chosen over interface because State holds instance state (context) which interfaces cannot hold in Java.
public abstract class State {
    protected Context context;
    public State(Context context) {
        this.context = context;
    }
    public abstract void handle();
    public void enter() { }
    public void exit() { }
}
Context composition of State

Context composes State with a private field and exposes synchronized setState to safely change states.

🎯 Tests whether candidate understands composition lifecycle: Context owns State instances and synchronized setState ensures atomic state transitions in multithreaded env.
public class Context {
    private volatile State currentState;
    public synchronized void setState(State state) {
        if (currentState != null) currentState.exit();
        currentState = state;
        currentState.enter();
    }
    public void request() {
        currentState.handle();
    }
}
ATMContext specialization

ATMContext extends Context to specialize for ATM FSM, reusing Context's state management and adding ATM-specific logic.

🎯 Tests whether candidate knows inheritance is used for specialization and Context's synchronized methods ensure thread-safe state changes without modifying base class.
public class ATMContext extends Context {
    public ATMContext() {
        setState(new IdleState(this));
    }
    // ATM-specific methods here
}
IdleState concrete realization

IdleState extends State and implements handle, enter, exit methods to define behavior for the idle state.

🎯 Tests whether candidate understands realization inheritance: concrete states extend abstract State and override behavior, enabling OCP for adding new states without modifying Context.
public class IdleState extends State {
    public IdleState(Context context) {
        super(context);
    }
    @Override
    public void handle() {
        // handle idle state logic
    }
    @Override
    public void enter() {
        // enter idle state
    }
    @Override
    public void exit() {
        // exit idle state
    }
}
📐
Class Diagram
Class Diagram
       +----------------+
       | <<Abstract>>   |
       |     State      |
       +----------------+
       | -context: Context|
       +----------------+
       | +handle(): void |
       | +enter(): void  |
       | +exit(): void   |
       +----------------+
              │ extends
              │
       +------------------------+
       |    IdleState           |
       +------------------------+
       | +handle(): void        |
       | +enter(): void         |
       | +exit(): void          |
       +------------------------+
              │
              │
       +------------------------+
       |  ATMContext            |
       +------------------------+
       | -currentState: State   |
       +------------------------+
       | +setState(State): void | [sync]
       | +request(): void       |
       +------------------------+
              ◆ composition
              │
       +------------------------+
       |  Context               |
       +------------------------+
       | -currentState: State   |
       +------------------------+
       | +setState(State): void | [sync]
       | +request(): void       |
       +------------------------+

This diagram models the State pattern for FSMs in ATM, Elevator, and Vending Machine contexts using Java-specific constructs. The abstract State class holds a reference to Context, enabling shared state and behavior, which interfaces cannot hold in Java. Context composes State instances and uses synchronized setState to ensure atomic state transitions, enforcing thread safety. ATMContext specializes Context via inheritance, demonstrating the Open-Closed Principle by extending without modifying base classes. Concrete states like IdleState realize State by overriding behavior methods, enabling extensibility. The use of volatile on currentState ensures visibility across threads. Overall, the design leverages Java's abstract classes, composition lifecycle, synchronized methods, and inheritance to implement a robust, extensible FSM.

Primary Focus

✓ Abstract class vs interface for shared state + Composition lifecycle + Realization inheritance + State pattern OCP

Practice

(1/5)
1. In designing the Chess game, should the Piece abstraction be an abstract class or an interface, and why?
easy
A. Abstract class, because interfaces cannot enforce method implementation.
B. Interface, because pieces only declare move behavior without shared state.
C. Interface, because Java interfaces can hold state since Java 8.
D. Abstract class, because pieces share common state like position and color.

Solution

  1. Step 1: Analyze shared state among pieces

    All pieces share common state such as position on the board and color, which is best encapsulated in a base class.
  2. Step 2: Evaluate abstract class vs interface

    Abstract classes allow shared state and common method implementations, while interfaces primarily declare behavior without state.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Shared state -> abstract class preferred over interface [check]
Hint: Shared state? Use abstract class, not interface [check]
Common Mistakes:
2. You want to add a new WeekendFeeStrategy to the existing chain of responsibility-based parking fee system. Which change respects the Open-Closed Principle (OCP) and Dependency Inversion Principle (DIP)?
medium
A. Modify the existing FeeHandler class to add weekend fee logic inside its handleRequest() method.
B. Create a subclass WeekendFeeHandler extending FeeHandler and override handleRequest() with weekend logic.
C. Create a new WeekendFeeHandler implementing the FeeStrategy interface and add it to the chain without changing existing handlers.
D. Add a boolean flag isWeekend to FeeHandler and branch logic based on it.

Solution

  1. Step 1: Understand OCP and DIP

    OCP requires extending behavior without modifying existing code; DIP requires depending on abstractions, not concretions.
  2. Step 2: Evaluate options

    Modify the existing FeeHandler class to add weekend fee logic inside its handleRequest() method. modifies existing class, violating OCP; Create a new WeekendFeeHandler implementing the FeeStrategy interface and add it to the chain without changing existing handlers. adds new handler, respecting OCP and DIP; Add a boolean flag isWeekend to FeeHandler and branch logic based on it. adds flag inside existing handler, violating OCP; Create a subclass WeekendFeeHandler extending FeeHandler and override handleRequest() with weekend logic. subclasses but may cause tight coupling and violates DIP if chain depends on concrete classes.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    New handler class added without modifying existing code [check]
Hint: Add new handler class, don't modify existing ones [check]
Common Mistakes:
3. In a multi-threaded notification system, the sendNotification() method checks if a channel is available before sending. Without synchronizing this method, what exact sequence of thread interleaving causes duplicate notifications to be sent?
medium
A. Thread 1 updates channel status after sending; Thread 2 reads stale status and retries sending.
B. Thread 1 sends notification; Thread 2 waits until Thread 1 finishes sending.
C. Thread 1 and Thread 2 both block on a lock and then send sequentially.
D. Thread 1 checks isAvailable() -> true, context switch; Thread 2 checks isAvailable() -> true; both send notifications concurrently.

Solution

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

    Without synchronization, both threads can see the channel as available before either marks it busy.
  2. Step 2: Trace thread interleaving

    Thread 1 checks availability -> true, context switch; Thread 2 checks availability -> true; both proceed to send, causing duplicate notifications.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Unsynchronized check-then-act allows concurrent sends [check]
Hint: Check-then-act without lock -> race, double send [check]
Common Mistakes:
4. In the Airline Reservation System, if the reserveSeat() method is not synchronized, which exact sequence of thread interleaving causes double-booking of the same seat?
medium
A. Thread 1 and Thread 2 both fail to read seat status due to visibility issues, causing booking failure.
B. Thread 1 reads seat as available, Thread 2 reads seat as unavailable, both proceed to book.
C. Thread 1 locks seat, Thread 2 waits; Thread 1 releases lock after booking.
D. Thread 1 checks seat availability -> true, context switch before booking; Thread 2 checks availability -> true, both book seat.

Solution

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

    Without synchronization, Thread 1 reads seat as available but is preempted before booking; Thread 2 also reads available and proceeds.
  2. Step 2: Both threads book the same seat concurrently

    Because no lock or atomic operation protects the check-and-book sequence, double-booking occurs.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Check-then-act gap without synchronization -> double-booking [check]
Hint: Check seat available -> context switch -> both book [check]
Common Mistakes:
5. The Airline Reservation System needs to support ElectricCar vehicles requiring ChargingSpot parking. What is the minimum change to the current Java design to support this 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 base class to include charging capability and add ChargingSpot as a new subclass of Spot.
C. Create a new Vehicle hierarchy for electric cars and a separate ParkingLot for charging spots.
D. Add a boolean isElectric field to Vehicle and conditionally handle charging spots in existing Spot classes.

Solution

  1. Step 1: Identify extensibility requirements

    Adding ElectricCar and ChargingSpot must not modify existing classes to respect OCP and avoid class explosion.
  2. Step 2: Minimal change approach

    Adding new enum values and creating new subclasses for ElectricCar and ChargingSpot, plus updating compatibility externally, extends functionality without changing existing code.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New enums + subclasses + external compatibility update -> no existing class change [check]
Hint: New enums + subclasses + external map -> no existing class edits [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