Command Pattern: Encapsulating Actions
Wrap requests as Command objects to support undo/redo and macro recording.
Command Pattern: Encapsulating Actions is a free Java Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The Command Intent
Command encapsulates a request as an object, allowing parameterization of clients with different requests, queuing, logging, and undoable operations.
Command Interface
Define an interface with an execute() method and optionally an undo() method. Each command object knows how to perform and reverse one action.
public interface Command {
void execute();
void undo();
}Concrete Command: TextEditor
Each concrete command encapsulates a receiver and the action parameters. Execute performs the action; undo reverses it.
public class InsertTextCommand implements Command {
private final TextEditor editor;
private final String text;
private final int position;
public InsertTextCommand(TextEditor editor, String text, int pos) {
this.editor = editor; this.text = text; this.position = pos;
}
public void execute() { editor.insert(position, text); }
public void undo() { editor.delete(position, text.length()); }
}Invoker: CommandHistory
The invoker holds a history of executed commands. It calls execute() and pushes to a stack. Undo pops and calls undo().
public class CommandHistory {
private final Deque<Command> history = new ArrayDeque<>();
public void execute(Command cmd) {
cmd.execute();
history.push(cmd);
}
public void undo() {
if (!history.isEmpty()) history.pop().undo();
}
}Undo / Redo Stack
Add a redo stack: when undoing, push to the redo stack; when redoing, pop from the redo stack and re-execute.
private final Deque<Command> undoStack = new ArrayDeque<>();
private final Deque<Command> redoStack = new ArrayDeque<>();
public void redo() {
if (!redoStack.isEmpty()) {
Command cmd = redoStack.pop();
cmd.execute();
undoStack.push(cmd);
}
}Macro Command
A macro command is a composite that holds a list of commands and executes them in sequence. Undo executes the reverses in reverse order.
public class MacroCommand implements Command {
private final List<Command> commands;
public MacroCommand(List<Command> commands) { this.commands = commands; }
public void execute() { commands.forEach(Command::execute); }
public void undo() { for (int i = commands.size()-1; i>=0; i--) commands.get(i).undo(); }
}Command Queue for Task Processing
Store commands in a queue and process them asynchronously. A worker thread dequeues and executes commands — decoupling producers from the execution thread.
BlockingQueue<Command> queue = new LinkedBlockingQueue<>();
// Producer:
queue.put(new SendEmailCommand(recipient, subject, body));
// Consumer thread:
Command cmd = queue.take();
cmd.execute();Command with Executor
Wrap commands as Runnable lambdas and submit them to an ExecutorService — the lambda is the command object.
ExecutorService exec = Executors.newFixedThreadPool(4);
exec.submit(() -> sendEmail(recipient, subject));
exec.submit(() -> generateReport(params));Logging Commands for Audit
Serializable Command objects can be persisted to a log. On recovery, replay them to reconstruct the final state — the basis of Event Sourcing.
void execute(Command cmd) {
cmd.execute();
auditLog.append(cmd.toString()); // log every action
history.push(cmd);
}GUI Action Buttons
In GUI frameworks, each button or menu item holds a Command. Clicking the button calls command.execute(). Swap commands at runtime to change button behavior.
Button saveBtn = new Button("Save");
saveBtn.setOnAction(() -> new SaveDocumentCommand(doc).execute());Command vs Strategy
Both encapsulate behavior. Strategy encapsulates an algorithm that can be swapped at runtime. Command encapsulates a complete request, including its parameters and receiver, supporting history and queuing.
Command in Spring
Spring Batch's Tasklet and Spring Integration's MessageHandler are application-level command patterns. Each Tasklet encapsulates one step of a batch job.
Quick Check
What additional method does Command add beyond execute() to support undo?
Recap
Command encapsulates actions as objects. Use it for undo/redo stacks, task queues, macro recording, and audit logging. Combine with an invoker that maintains command history.
Frequently asked questions
Is the “Command Pattern: Encapsulating Actions” lesson free?
Yes — the full text of “Command Pattern: Encapsulating Actions” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.
What will I learn in “Command Pattern: Encapsulating Actions”?
Wrap requests as Command objects to support undo/redo and macro recording. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Java Academy?
No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Command Pattern: Encapsulating Actions” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Java Academy lesson?
Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Observer Pattern: Event Notification
- Strategy Pattern: Interchangeable Algorithms
- Command Pattern: Encapsulating Actions
- Template Method: Defining Algorithm Skeletons