Jump into concepts and practice - no test required
or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Design: Command Pattern Implementation
Design the core command pattern structure including command interface, concrete commands, invoker, and receiver. Out of scope: UI integration and persistence of command history.
Functional Requirements
FR1: Allow encapsulation of requests as objects
FR2: Support undo and redo operations
FR3: Enable queuing and logging of commands
FR4: Decouple the object that invokes the operation from the one that knows how to perform it
Non-Functional Requirements
NFR1: Must support multiple command types with different parameters
NFR2: Commands should be executed asynchronously if needed
NFR3: Undo/redo operations should be efficient
NFR4: System should be extensible to add new commands without modifying existing code
Think Before You Design
Questions to Ask
❓ Question 1
❓ Question 2
❓ Question 3
❓ Question 4
❓ Question 5
Key Components
Command interface or abstract class
Concrete command classes implementing the interface
Invoker that calls commands
Receiver that performs the actual work
Command history stack for undo/redo
Design Patterns
Command pattern
Memento pattern for undo/redo state
Queue or buffer for asynchronous command execution
Composite pattern if commands can be grouped
Reference Architecture
Client
|
v
Invoker ---> Command Interface <--- Concrete Commands ---> Receiver
|
v
Command History (Stack for Undo/Redo)
Components
Command Interface
Abstract class or interface
Defines execute(), undo() methods for commands
Concrete Commands
Classes implementing Command Interface
Encapsulate specific actions and parameters
Invoker
Class
Calls execute() on commands and manages command history
Receiver
Class
Performs the actual operations requested by commands
Command History
Stack data structure
Stores executed commands for undo/redo
Request Flow
1. Client creates a Concrete Command with a Receiver and parameters
2. Client passes the command to the Invoker
3. Invoker calls execute() on the command
4. Command calls appropriate method(s) on the Receiver to perform action
5. Invoker stores the command in Command History stack
6. For undo, Invoker calls undo() on the last command from history
7. For redo, Invoker calls execute() again on the undone command
Database Schema
Not applicable - this is an in-memory design pattern implementation without persistent storage.
Scaling Discussion
Bottlenecks
Large number of commands causing memory pressure in history stack
Complex undo/redo logic for commands with side effects
Synchronous execution blocking invoker if commands take long
Difficulty adding new command types if interface is not flexible
Solutions
Limit history size or use persistent storage for command logs
Use Memento pattern to capture state snapshots for undo
Implement asynchronous command execution with queues and worker threads
Design command interface with extensibility in mind and use polymorphism
Interview Tips
Time: 10 minutes to clarify requirements and scope, 20 minutes to design components and data flow, 15 minutes to discuss scaling and trade-offs
Explain how command pattern decouples invoker and receiver
Describe how undo/redo is supported via command history
Discuss extensibility for adding new commands
Mention asynchronous execution for scalability
Highlight real-world use cases like GUI actions, transaction management
Practice
(1/5)
1. What is the main purpose of the Command pattern in system design?
easy
A. To create multiple instances of a class efficiently
B. To ensure only one instance of a class exists
C. To define a family of algorithms and make them interchangeable
D. To encapsulate a request as an object, allowing parameterization and queuing of requests
Solution
Step 1: Understand the Command pattern role
The Command pattern encapsulates a request as an object, which allows you to parameterize clients with queues, requests, and operations.
Step 2: Compare with other patterns
Creating multiple instances relates to Prototype or Factory, a family of algorithms to Strategy, and a single instance to Singleton; these are not Command.
Final Answer:
To encapsulate a request as an object, allowing parameterization and queuing of requests -> Option D
Quick Check:
Command pattern = encapsulate request [OK]
Hint: Command pattern = wrap action as object for flexibility [OK]
Common Mistakes:
Confusing Command with Singleton or Factory patterns
Thinking Command creates instances instead of encapsulating actions
Mixing Command with Strategy pattern
2. Which of the following is the correct method signature for the execute method in a Command interface?
easy
A. void execute(String[] args);
B. void execute();
C. boolean execute(String commandName);
D. int execute(int commandId);
Solution
Step 1: Recall Command interface basics
The Command interface typically defines a simple execute() method without parameters to perform the action.
Step 2: Analyze options
The options with parameters (String[], int commandId, String commandName) or return types are not standard in Command pattern interfaces; the command object itself holds necessary data.
Final Answer:
void execute(); -> Option B
Quick Check:
Command execute method = void execute() [OK]
Hint: Command execute usually has no parameters [OK]
Common Mistakes:
Adding parameters to execute method unnecessarily
Confusing Command with other patterns that require arguments
Assuming execute returns a value
3. Given the following code snippet implementing the Command pattern, what will be the output?
class Light {
turnOn() { console.log('Light is ON'); }
turnOff() { console.log('Light is OFF'); }
}
class TurnOnCommand {
constructor(light) { this.light = light; }
execute() { this.light.turnOn(); }
}
class TurnOffCommand {
constructor(light) { this.light = light; }
execute() { this.light.turnOff(); }
}
class RemoteControl {
setCommand(command) { this.command = command; }
pressButton() { this.command.execute(); }
}
const light = new Light();
const remote = new RemoteControl();
remote.setCommand(new TurnOnCommand(light));
remote.pressButton();
remote.setCommand(new TurnOffCommand(light));
remote.pressButton();
medium
A. Light is ON\nLight is OFF
B. Light is OFF\nLight is ON
C. Light is ON\nLight is ON
D. Light is OFF\nLight is OFF
Solution
Step 1: Trace first command execution
The remote sets the command to TurnOnCommand and calls execute, which calls light.turnOn(), printing 'Light is ON'.
Step 2: Trace second command execution
The remote sets the command to TurnOffCommand and calls execute, which calls light.turnOff(), printing 'Light is OFF'.
Final Answer:
Light is ON\nLight is OFF -> Option A
Quick Check:
TurnOn then TurnOff commands print ON then OFF [OK]
Hint: Follow command set and execute calls step-by-step [OK]
Common Mistakes:
Mixing order of commands
Assuming commands execute immediately without setting
Confusing method names turnOn and turnOff
4. In the following code, what is the main issue that prevents the Command pattern from working correctly?
class Light {
turnOn() { console.log('Light is ON'); }
}
class TurnOnCommand {
constructor() { }
execute() { this.light.turnOn(); }
}
const light = new Light();
const command = new TurnOnCommand();
command.execute();
medium
A. The execute method should return a value
B. The Light class is missing the turnOff method
C. The TurnOnCommand constructor does not receive or store the Light object
D. The command object is not instantiated properly
Solution
Step 1: Check TurnOnCommand constructor
The constructor does not accept or assign the Light object to this.light, so this.light is undefined.
Step 2: Analyze execute method call
Calling this.light.turnOn() fails because this.light is undefined, causing an error.
Final Answer:
The TurnOnCommand constructor does not receive or store the Light object -> Option C
Quick Check:
Missing light reference in command = error [OK]
Hint: Ensure command stores receiver object before execute [OK]
Common Mistakes:
Ignoring missing receiver object in command
Thinking missing turnOff method causes error here
Assuming execute must return a value
5. You are designing a text editor with undo functionality using the Command pattern. Which design choice best supports undo operations efficiently?
hard
A. Store a history stack of Command objects and call an undo() method on the last command
B. Keep a log of all text changes as strings and replay them to undo
C. Use a single Command object that modifies text directly without history
D. Implement undo by reloading the entire document from disk
Solution
Step 1: Understand undo with Command pattern
Each Command object should implement both execute() and undo() methods to reverse its action.
Step 2: Evaluate design choices
Storing a history stack of Command objects allows calling undo() on the last command efficiently. Other options either lack command encapsulation or are inefficient.
Final Answer:
Store a history stack of Command objects and call an undo() method on the last command -> Option A
Quick Check:
Undo = command history stack with undo() [OK]
Hint: Undo needs command history with undo method [OK]