Bird
Raised Fist0

Command Pattern - Encapsulating Operations for Undo, Redo, Queue

LLDeasyInterview freq: common
Choose your preparation mode4 modes available
▶
Class Trace
Step 1/3
Command abstract class

Command is an abstract class holding a Receiver reference and synchronized execute and undo methods.

🎯 Tests whether candidate knows abstract class is used instead of interface because Command holds state (Receiver) and method implementations requiring synchronization.
public abstract class Command {
    protected Receiver receiver;
    public Command(Receiver receiver) {
        this.receiver = receiver;
    }
    public synchronized abstract void execute() throws CommandExecutionException;
    public synchronized abstract void undo() throws CommandExecutionException;
}
ConcreteCommand realization

ConcreteCommand extends Command and implements execute and undo by delegating to Receiver's methods.

🎯 Tests understanding of realization relationship and how ConcreteCommand encapsulates a request by calling Receiver methods, enforcing OCP by adding new commands without modifying Command.
public class ConcreteCommand extends Command {
    public ConcreteCommand(Receiver receiver) {
        super(receiver);
    }
    @Override
    public synchronized void execute() throws CommandExecutionException {
        receiver.action();
    }
    @Override
    public synchronized void undo() throws CommandExecutionException {
        receiver.revertAction();
    }
}
Invoker composition with Command queue

Invoker composes a queue of Commands and provides methods to execute and undo commands, managing command lifecycle internally.

🎯 Tests whether candidate understands composition lifecycle: Invoker owns Commands in queue and controls their execution order, enforcing Single Responsibility and Command pattern encapsulation.
public class Invoker {
    private final Queue<Command> commandQueue = new LinkedList<>();
    public synchronized void executeCommand(Command command) throws CommandExecutionException {
        command.execute();
        commandQueue.add(command);
    }
    public synchronized void undoCommand() throws CommandExecutionException {
        if (!commandQueue.isEmpty()) {
            Command cmd = commandQueue.poll();
            cmd.undo();
        }
    }
}
📐
Class Diagram
Class Diagram
       +----------------------+
       | <<Abstract>>         |
       | Command              |
       +----------------------+
       | - receiver: Receiver |
       +----------------------+
       | + execute() [sync]   |
       | + undo() [sync]      |
       +----------------------+
               │ extends
               │
       +----------------------+
       | ConcreteCmd          |
       +----------------------+
       | + execute() [sync]   |
       | + undo() [sync]      |
       +----------------------+
               │
               │ composition ◆
               ▼
       +----------------------+
       | Receiver             |
       +----------------------+
       | + action()           |
       | + revertAction()     |
       +----------------------+
               ▲
               │ composition ◆
               │
       +----------------------+
       | Invoker              |
       +----------------------+
       | - commandQueue: Queue|
       +----------------------+
       | + executeCommand()   |
       | + undoCommand()      |
       +----------------------+

This diagram illustrates the Command pattern with Command as an abstract class holding a Receiver reference and synchronized execute and undo methods to ensure thread safety. ConcreteCommand realizes Command by implementing these methods and delegating to Receiver, demonstrating the realization relationship and enforcing the Open-Closed Principle by allowing new commands without modifying existing code. Invoker composes a queue of Command objects, managing their lifecycle and execution order, which enforces composition and Single Responsibility Principle. The use of checked CommandExecutionException enforces explicit error handling in command execution and undo operations. This design leverages Java-specific features like synchronized methods for concurrency control and abstract classes for shared state, ensuring extensibility and thread-safe command execution.

Primary Focus

✓ Abstract class vs interface for shared state + Composition lifecycle + Exception handling with checked exception

Practice

(1/5)
1. In designing the Track abstraction for the music library, should Track be an abstract class or an interface? Consider that each Track has state like duration and title, and behavior like play() and pause().
easy
A. Interface, because state can be stored externally and behavior implemented in separate classes.
B. Interface, because it allows multiple inheritance and all methods are abstract.
C. Abstract class, because it can hold shared state and provide default behavior implementations.
D. Abstract class, because it enforces immutability of Track objects.

Solution

  1. Step 1: Analyze state and behavior requirements

    Track has shared state (duration, title) and common behavior (play, pause) that can be implemented once.
  2. Step 2: Abstract class vs interface for state and behavior

    Abstract class can hold state fields and provide default method implementations, while interfaces cannot hold instance state.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    State + default behavior -> abstract class [check]
Hint: Stateful base class? Use abstract class, not interface [check]
Common Mistakes:
2. In designing a Vehicle abstraction for a parking system, should Vehicle be an abstract class or an interface if it needs to hold state like licensePlate and provide default behavior for getSize()? Why?
easy
A. Abstract class, because it can hold shared state and provide default method implementations.
B. Interface, because it allows multiple inheritance and enforces method contracts without state.
C. Interface, because Java 8+ interfaces can have default methods and fields for state.
D. Abstract class, because it forces all subclasses to implement all methods explicitly.

Solution

  1. Step 1: Analyze state and behavior requirements

    Vehicle needs to hold state (licensePlate) and provide default behavior (getSize), which interfaces cannot hold as fields.
  2. Step 2: Choose abstraction supporting state and default behavior

    Abstract classes support instance variables and method implementations; interfaces cannot hold instance state.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Abstract class supports state and default behavior -> correct choice [check]
Hint: State needs abstract class; interfaces can't hold instance fields [check]
Common Mistakes:
3. In a vending machine modeled with the State pattern, each state class implements the same interface and handles input differently. Which OOP concept does this best illustrate?
easy
A. Inheritance to share common state variables across states
B. Encapsulation to hide the internal state machine logic from clients
C. Abstraction to define a generic state without implementation
D. Polymorphism to delegate behavior to state-specific classes

Solution

  1. Step 1: Identify the role of state classes

    Each state class implements the same interface but provides different behavior for the same method calls, which is polymorphism.
  2. Step 2: Eliminate other options

    Inheritance alone does not explain different behaviors; encapsulation hides data but does not delegate behavior; abstraction defines interface but does not implement behavior.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    State classes override interface methods -> polymorphism [check]
Hint: State pattern uses polymorphism to vary behavior by state [check]
Common Mistakes:
4. In the messaging system, the DeliveryStatus class has a method markDelivered() that updates the delivery state. Without synchronizing this method, which exact thread interleaving causes inconsistent delivery status updates?
medium
A. Thread 1 reads status as undelivered, context switch; Thread 2 reads undelivered, both set delivered, overwriting each other's update.
B. Thread 1 calls markDelivered() while Thread 2 calls markFailed(), causing deadlock.
C. Thread 1 updates status to delivered, but Thread 2 never sees the update due to caching.
D. Thread 1 and Thread 2 both call markDelivered() simultaneously, causing a crash.

Solution

  1. Step 1: Identify the race condition in markDelivered()

    Without synchronization, two threads can read the undelivered status before either writes the delivered status.
  2. Step 2: Trace the interleaving causing lost update

    Thread 1 reads undelivered -> context switch -> Thread 2 reads undelivered -> both write delivered, one overwriting the other's update.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Check-then-act without sync -> lost update race condition [check]
Hint: Check-then-act gap -> lost update race [check]
Common Mistakes:
5. The system needs to support ElectricCar and ChargingSpot without modifying existing Vehicle or Spot classes. What is the minimum change to support this extensibility in Java?
hard
A. Modify Vehicle class to include a boolean isElectric and add charging logic inside existing methods.
B. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update compatibility map externally.
C. Create a new ElectricVehicle interface and modify Spot to check for it explicitly.
D. Add charging logic inside Vehicle and Spot classes directly, breaking encapsulation.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Enums can be extended with new constants; subclassing ElectricCar adds new behavior without changing Vehicle.
  2. Step 2: Update compatibility externally

    Updating SpotCompatibility.COMPATIBILITY_MAP externally respects OCP and avoids class explosion or god 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 -> minimal 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