Create the Receiver object which holds the state and the Invoker which manages command execution and undo/redo stacks.
💡 Setting up these objects is essential because the Receiver performs actions, and the Invoker controls command execution and history.
Line:receiver = Receiver()
invoker = Invoker()
💡 The Receiver and Invoker are distinct roles: Receiver knows how to perform actions; Invoker manages command lifecycle.
insert
Create CommandA and Execute
Create CommandA (AddCommand with value 1) linked to the Receiver and execute it via Invoker. CommandA is pushed onto the undo stack; redo stack is cleared.
💡 Executing a command changes the receiver's state and records the command for potential undo.
💡 Commands can be stored for deferred execution, enabling flexible command management.
execute
Execute Command Queue
Invoker executes all commands in the queue in order: CommandC then CommandD. Each command is executed, pushed onto undo stack, and redo stack is cleared after each execution.
💡 Executing queued commands applies their effects and updates undo/redo stacks as if executed individually.
Line:invoker.execute_queue()
💡 Batch execution of queued commands integrates seamlessly with undo/redo mechanism.
reconstruct
Final State: Receiver and Stacks
All commands have been executed or undone/redone as per input. The receiver's state reflects all executed commands. Undo stack contains all executed commands. Redo stack is empty. Command queue is empty.
💡 The final state shows the cumulative effect of all operations and the current undo/redo history.
Line:# No code executed, final state snapshot
💡 The undo and redo stacks accurately track command history, enabling flexible state rollback and reapplication.
Command Pattern - Undo/Redo, Request Queuing & Logging - Watch the Algorithm Execute, Step by Step
Watching the algorithm execute step-by-step reveals how commands are managed, how undo and redo stacks interact, and how queued commands are processed, which is difficult to grasp from code alone.
Step 1/8
·Active fill★Answer cell
Separation of concerns: Receiver handles state changes; Invoker manages command execution and history stacks.
Receiver
−state: int
+action()
+revert()
Invoker
−undo_stack: List<Command>
−redo_stack: List<Command>
−command_queue: List<Command>
+execute_command()
+undo()
+redo()
+2 more
Command encapsulation and execution with history tracking.
AddCommand
−receiver: Receiver
−value: int
+execute()
+undo()
Receiver
−state: int
+action()
+revert()
Invoker
−undo_stack: List<Command>
−redo_stack: List<Command>
−command_queue: List<Command>
+execute_command()
+undo()
+redo()
+2 more
AddCommand → Receiver (1:1)
Sequential command execution with undo stack growth.
AddCommand
−receiver: Receiver
−value: int
+execute()
+undo()
Receiver
−state: int
+action()
+revert()
Invoker
−undo_stack: List<Command>
−redo_stack: List<Command>
−command_queue: List<Command>
+execute_command()
+undo()
+redo()
+2 more
AddCommand → Receiver (1:1)
Undo operation moves command from undo to redo stack and reverts receiver state.
AddCommand
−receiver: Receiver
−value: int
+execute()
+undo()
Receiver
−state: int
+action()
+revert()
Invoker
−undo_stack: List<Command>
−redo_stack: List<Command>
−command_queue: List<Command>
+execute_command()
+undo()
+redo()
+2 more
AddCommand → Receiver (1:1)
Redo operation moves command from redo to undo stack and reapplies receiver state.
AddCommand
−receiver: Receiver
−value: int
+execute()
+undo()
Receiver
−state: int
+action()
+revert()
Invoker
−undo_stack: List<Command>
−redo_stack: List<Command>
−command_queue: List<Command>
+execute_command()
+undo()
+redo()
+2 more
AddCommand → Receiver (1:1)
Command queue stores commands for batch execution later.
AddCommand
−receiver: Receiver
−value: int
+execute()
+undo()
Receiver
−state: int
+action()
+revert()
Invoker
−undo_stack: List<Command>
−redo_stack: List<Command>
−command_queue: List<Command>
+execute_command()
+undo()
+redo()
+2 more
AddCommand → Receiver (1:1)
Batch execution integrates queued commands into undo/redo stacks.
AddCommand
−receiver: Receiver
−value: int
+execute()
+undo()
Receiver
−state: int
+action()
+revert()
Invoker
−undo_stack: List<Command>
−redo_stack: List<Command>
−command_queue: List<Command>
+execute_command()
+undo()
+redo()
+2 more
AddCommand → Receiver (1:1)
Final state shows command pattern managing state and history stacks correctly.
Receiver
−state: int
+action()
+revert()
Invoker
−undo_stack: List<Command>
−redo_stack: List<Command>
−command_queue: List<Command>
+execute_command()
+undo()
+redo()
+2 more
AddCommand → Receiver (1:1)
Key Takeaways
✓ Commands encapsulate all information needed to perform and undo an action, enabling flexible execution and history management.
This insight is hard to see from code alone because the separation of command logic from execution context is subtle without visualization.
✓ Undo and redo stacks maintain a clear history of executed and undone commands, allowing precise state rollback and reapplication.
Visualizing stack changes clarifies how commands move between undo and redo, which is often confusing when reading code.
✓ Queuing commands allows batching multiple operations for later execution, integrating seamlessly with undo/redo mechanisms.
Seeing queued commands and their execution order helps understand how deferred execution fits into the pattern.
Practice
(1/5)
1. You are designing a system where multiple unrelated classes must guarantee implementation of certain methods but share no common code. Which abstraction mechanism is most appropriate to enforce this contract?
easy
A. Use an abstract class to define the methods and provide partial implementation.
B. Use an abstract class only if all classes share a common ancestor.
C. Use a concrete class and rely on inheritance for code reuse.
D. Use an interface to declare the methods without any implementation.
Solution
Step 1: Identify the need for a contract without shared code
Interfaces define method signatures without implementation, perfect for unrelated classes needing a common contract.
Step 2: Why abstract classes are less suitable here
Abstract classes provide partial implementation and require a common ancestor, which unrelated classes lack.
Step 3: Why concrete classes and inheritance don't fit
Concrete classes imply implementation and inheritance assumes a hierarchy, which is not guaranteed.
Final Answer:
Option D -> Option D
Quick Check:
Interfaces enforce contracts without imposing inheritance or shared code.
Hint: Use interfaces when only a contract is needed, abstract classes when sharing code.
Common Mistakes:
Assuming abstract classes are always better for abstraction.
Confusing contract enforcement with code reuse.
Believing unrelated classes can share an abstract class.
2. You are designing a system for different types of vehicles where some can fly and some can float on water. Which design approach best supports adding new capabilities like flying or floating without modifying existing vehicle classes?
easy
A. Use inheritance to create subclasses like FlyingCar and FloatingCar from Vehicle
B. Use a single Vehicle class with flags indicating if it can fly or float
C. Use composition by creating separate capability classes like FlyBehavior and FloatBehavior and compose them with Vehicle
D. Use inheritance and override methods in each subclass to add flying or floating behavior
Solution
Step 1: Identify the problem with inheritance here
Inheritance leads to a combinatorial explosion of subclasses (FlyingCar, FloatingCar, FlyingFloatingCar), making the design rigid and hard to maintain.
Step 2: Understand composition benefits
Composition allows attaching behaviors dynamically via separate classes (FlyBehavior, FloatBehavior), promoting flexibility and easier extension.
Step 3: Analyze other options
Options A and C rely on inheritance, causing tight coupling and poor scalability. Use a single Vehicle class with flags indicating if it can fly or float uses flags, which leads to complex conditional logic and violates single responsibility.
Final Answer:
Option C -> Option C
Quick Check:
Composition supports adding new capabilities without modifying existing classes, enhancing maintainability and flexibility.
Hint: Composition lets you add capabilities by combining behaviors, inheritance forces rigid hierarchies.
Common Mistakes:
Assuming inheritance is always better for code reuse
Using flags instead of behaviors leads to messy conditionals
3. Trace the sequence of events when a player rolls the dice and lands on a ladder in a well-designed Snake and Ladder game. Which of the following best describes the correct order of internal state changes?
easy
A. Player rolls dice -> GameController calculates new position -> Board checks for ladder -> GameController updates Player position accordingly
B. Player rolls dice -> Player position updated -> Board checks for ladder -> Player position updated again if ladder found
C. Player rolls dice -> Board updates Player position directly if ladder found -> Player notified of new position
D. Player rolls dice -> Dice notifies Board -> Board updates Player position -> GameController confirms move
Solution
Step 1: Dice roll triggers GameController
Dice generates number; GameController uses it to calculate tentative position.
Step 2: Board checks for ladder or snake
GameController queries Board to see if new position has ladder or snake.
Step 3: GameController updates Player position
Based on Board's info, GameController updates Player's position accordingly.
Step 4: Player position is finalized
Player's position reflects ladder climb if applicable.
Final Answer:
Option A -> Option A
Quick Check:
Only GameController manages state changes; Board is queried but does not update Player directly.
Hint: GameController mediates all state changes after dice roll [OK]
Common Mistakes:
Assuming Player updates position before Board check
Believing Board directly updates Player position
Thinking Dice notifies Board
4. Which of the following statements about the Interface Segregation Principle (ISP) is INCORRECT?
medium
A. ISP aims to reduce the number of interfaces to simplify the system.
B. Clients should only depend on the interfaces that are relevant to them.
C. ISP encourages creating multiple specific interfaces rather than one general-purpose interface.
D. ISP helps avoid forcing clients to implement methods they do not use.
Solution
Step 1: Recall ISP's core principle
ISP promotes splitting interfaces so clients depend only on what they need, often increasing interface count.
Step 2: Analyze options
ISP aims to reduce the number of interfaces to simplify the system. incorrectly states ISP reduces the number of interfaces; in reality, it often increases them to avoid fat interfaces. Options A, B, and D correctly describe ISP goals.
Final Answer:
Option A -> Option A
Quick Check:
ISP is about interface granularity, not minimizing interface count.
Hint: ISP splits interfaces; it doesn't minimize their count.
Common Mistakes:
Confusing ISP with interface minimization
Assuming fewer interfaces always mean better design
Ignoring client-specific interface needs
5. What is the time complexity of processing a payment using the optimal strategy pattern implementation with dependency injection, assuming the payment method is already selected?
medium
A. O(n) where n is the number of payment methods
B. O(log n) due to searching the strategy in a factory method
C. O(1) constant time since the strategy is injected and pay() is a direct call
D. O(n^2) because of nested conditional checks inside the strategy classes
Solution
Step 1: Identify the operation performed during payment
Once the strategy is injected, calling pay() is a direct method call without iteration or recursion.
Step 2: Analyze complexity of the pay() method
The pay() method executes a simple print statement, which is O(1).
Final Answer:
Option C -> Option C
Quick Check:
Direct method call with no loops or recursion is constant time [OK]
Hint: Injected strategy enables direct O(1) method call [OK]
Common Mistakes:
Assuming factory lookup or conditionals happen at payment time
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.