CHAPTER 15
Intermediate
Command Pattern
Updated: May 16, 2026
35 min read
# CHAPTER 15
Command Pattern
1. Introduction
Imagine building a text editor. You have a "Save" button in the top menu. You also have a "Save" shortcut (Ctrl+S). You also have a "Save" option in the right-click context menu. If you write the complex logic for saving the file directly inside the UI click-handler code for all three of those triggers, you have duplicated heavy business logic three times. Worse, how do you implement an "Undo" feature if the actions are just floating functions? The Command Pattern solves this. It turns a request or an action into a standalone, physical object. In this chapter, we will master the Command Pattern, learning how to decouple UI from business logic, build robust asynchronous task queues, and engineer complex Undo/Redo systems.
2. Learning Objectives
By the end of this chapter, you will be able to:- Define the intent of the Command Pattern.
- Understand how encapsulating an action into an object creates architectural flexibility.
- Map the roles of the Sender (Invoker), the Command, and the Receiver.
- Architect an "Undo/Redo" history stack.
- Implement delayed execution for Task Queues.
3. The Core Concept
The Command pattern encapsulates a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.-
The Decoupling: The UI Button (The Sender) should not know *how* to save a file to a database. It should only know how to execute a
Commandobject.
-
The Objectification of Action: By turning an action into an object, you can store it in an array. If you have an array of "Executed Commands," you have a history log. If you loop backward through that array calling
undo(), you have just builtCtrl+Z.
4. The Four Actors
The Command pattern relies on a very specific, slightly complex structure.-
1.
The Receiver: The underlying business logic that actually does the work (e.g., The
Databaseor theTextDocument).
-
2.
The Command Interface: A simple contract, usually containing just
execute()andundo().
-
3.
The Concrete Command: The object that binds a specific action to a specific Receiver (e.g.,
SaveFileCommand).
-
4.
The Invoker (Sender): The UI button or shortcut manager. It holds the Command object and calls
execute()when clicked.
5. Task Queues and Asynchronous Execution
Because a Command is a physical object containing all the data it needs to execute, you don't have to execute it immediately. You can serialize the Command object, push it into a Redis queue, and have a background worker deserialize it and execute it 10 minutes later. The Command pattern is the foundation of all job queue architectures.6. UML Diagram
*Command Structure*
text
7. Code Example (PHP)
Let's build a simple Smart Home Remote with an Undo feature.
php
8. Best Practices
-
Mementos for Complex Undo: In the example above,
undo()was easy because the opposite of "On" is "Off." But what if the command is "Change Font Color to Red"? How does the Command know what the *previous* color was? *Best Practice:* Before a Concrete Command callsexecute(), it should save a snapshot (a Memento) of the Receiver's current state inside its own private variables. Then,undo()simply restores that saved snapshot.
9. Common Mistakes
-
Putting Logic in the Command: A Command should act as a dumb relay. It should *not* contain heavy business logic. If
SaveToDatabaseCommandcontains 50 lines of SQL queries, it is violating SRP. The Command should simply call$database->save(). The heavy logic belongs in the Receiver.
10. Mini Project: Build a Macro Recorder
-
1.
Create multiple Commands:
CopyCommand,PasteCommand,DeleteCommand.
-
2.
Create a
MacroCommandclass that implementsCommand. Its constructor accepts an array of other Commands.
-
3.
In
MacroCommand->execute(), loop through the array and callexecute()on every child command. You have just built a system to record and playback complex sequences of user actions!
11. Practice Exercises
- 1. Define the architectural role of the "Invoker" versus the "Receiver" in the Command Pattern. Why is decoupling them critical for GUI development?
- 2. Explain exactly how turning an action (like a button click) into a physical Object enables the creation of an "Undo/Redo" history stack.
12. MCQs with Answers
Question 1
An architect needs to implement a robust "Ctrl+Z" (Undo) feature for a complex graphic design application. Which behavioral design pattern is universally recognized as the standard solution for capturing and reversing user actions?
Question 2
In the Command Pattern architecture, which object is responsible for actually performing the heavy business logic (e.g., executing the SQL query to save the file)?
13. Interview Questions
- Q: Explain how the Command pattern facilitates the creation of asynchronous Job Queues (like AWS SQS or Redis queues). How does "objectifying" a request allow for delayed execution?
-
Q: Walk me through the implementation of a complex
undo()method. If a user deletes a block of text, how does theDeleteTextCommandobject know how to restore the exact text that was deleted?
- Q: Compare the Command Pattern with the Strategy Pattern. Both involve encapsulating behavior into objects and executing them via an interface. How do their structural intents differ?
14. FAQs
Q: Doesn't this create way too many tiny classes? A: Yes. A large app might have hundreds of Command classes (SaveCommand, CopyCommand, CutCommand). While it increases file count, it massively decreases complexity. Each class has one tiny responsibility and is perfectly testable in isolation.