Implement the Command pattern with undo. How does encapsulating a request as an object enable queues, logging, and undo/redo?
Recognising when to reify an action into an object with execute()/undo() to decouple invoker from receiver and gain history/queueing.
Command turns a request into a standalone OBJECT that bundles everything needed to perform it — the action, its target, and its parameters — behind a uniform interface (typically `execute()` and often `undo()`). The signal: you need to do more with an action than just run it immediately — queue it, log it, schedule/retry it, run it remotely, or (most tellingly) UNDO it. Because each command captures its own inputs and knows how to reverse itself, you can push executed commands onto a history stack and pop-and-`undo()` to walk backwards; a redo stack mirrors it. This also decouples the INVOKER (a button, a keyboard shortcut, a queue) from the RECEIVER (the object that actually does the work) — the invoker only knows it has something with `execute()`, so the same command can be triggered from a menu, a hotkey, or a script, and new commands don't require changing the invoker. Frontend manifestations are everywhere: Redux/Flux ACTIONS are commands (plain objects describing 'what happened' that a reducer executes; middleware can log/queue/replay them — time-travel debugging is literally re-executing a command log); editor undo/redo stacks; a command bus/CQRS on the backend; and macro-recording (a macro is just a list of commands). The trade-off is boilerplate — each action becomes an object — so reserve it for when you genuinely need undo, queuing, logging, or invoker/receiver decoupling; a direct method call is fine otherwise.
Undo/redo stacks, action logging/replay (Redux, time-travel), queuing or scheduling operations, macro recording, and decoupling UI triggers from the code that runs.
O(1) per execute/undo; O(n) history memory for n actions.