What if you could press a button and instantly undo or schedule any action without rewriting your code?
Why Command pattern in LLD? - Purpose & Use Cases
Start learning this pattern below
Jump into concepts and practice - no test required
Imagine you have a remote control with many buttons, and each button does a different task. Now, you want to add undo and redo features, or queue commands to run later. Doing all this by writing separate code for each button and feature quickly becomes messy and confusing.
Manually handling each action means you mix the code for what to do with when and how to do it. This leads to tangled code that is hard to change or extend. Adding new commands or features like undo requires rewriting many parts, increasing bugs and slowing development.
The Command pattern wraps each action into its own object. This separates the 'what to do' from 'when and how to do it'. It makes adding new commands, undo, redo, or queuing simple and clean without changing existing code.
if(button == 'play') { playSong(); } else if(button == 'stop') { stopSong(); } // no undo support
command = new PlayCommand(song); remote.setCommand(command); remote.pressButton(); // supports undo, redo, queue
It enables flexible, reusable, and extendable command execution with features like undo, redo, and scheduling without messy code changes.
In text editors, every user action like typing or deleting is a command object. This lets the editor easily undo or redo actions by replaying or reversing these commands.
Separates actions into command objects for clean code.
Makes adding undo, redo, and queuing easy.
Improves flexibility and maintainability of complex systems.
Practice
Command pattern in system design?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 DQuick Check:
Command pattern = encapsulate request [OK]
- Confusing Command with Singleton or Factory patterns
- Thinking Command creates instances instead of encapsulating actions
- Mixing Command with Strategy pattern
execute method in a Command interface?Solution
Step 1: Recall Command interface basics
The Command interface typically defines a simpleexecute()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 BQuick Check:
Command execute method = void execute() [OK]
- Adding parameters to execute method unnecessarily
- Confusing Command with other patterns that require arguments
- Assuming execute returns a value
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();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 AQuick Check:
TurnOn then TurnOff commands print ON then OFF [OK]
- Mixing order of commands
- Assuming commands execute immediately without setting
- Confusing method names turnOn and turnOff
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();Solution
Step 1: Check TurnOnCommand constructor
The constructor does not accept or assign the Light object tothis.light, sothis.lightis undefined.Step 2: Analyze execute method call
Callingthis.light.turnOn()fails becausethis.lightis undefined, causing an error.Final Answer:
The TurnOnCommand constructor does not receive or store the Light object -> Option CQuick Check:
Missing light reference in command = error [OK]
- Ignoring missing receiver object in command
- Thinking missing turnOff method causes error here
- Assuming execute must return a value
Solution
Step 1: Understand undo with Command pattern
Each Command object should implement bothexecute()andundo()methods to reverse its action.Step 2: Evaluate design choices
Storing a history stack of Command objects allows callingundo()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 AQuick Check:
Undo = command history stack with undo() [OK]
- Using string logs instead of command objects
- Not implementing undo in commands
- Reloading entire document is inefficient
