Behavioral 3 — Command
In one line
Wrap a request (and its receiver) into an object — enables undo/redo, queuing, logging, and macros.
Key ideas
- 01
Solves: execute later, undo, transactional behavior — GUI actions, job queues, task schedulers.
- 02
Command = execute(); history = stack of commands; undo = reversed execute.
- 03
Many distributed systems (job schedulers, workflow engines) are command patterns at scale.
- 04
Real-life example: a restaurant order slip. The waiter writes your order on paper (the command), the kitchen cooks it later. The slip can be queued, cancelled, or repeated.
- 05
Redo needs a second stack: undo pops from 'history' and pushes onto 'redo'. Any new command clears the redo stack.
Java / Spring map
- →
java.lang.Runnable; Spring's TaskExecutor; Quartz jobs.
Code & diagrams
Undoable text editor operations.
public interface Command { void execute(); void undo(); }
public final class TextBuffer {
private final StringBuilder sb = new StringBuilder();
public void append(String s) { sb.append(s); }
public void chop(int n) { sb.setLength(Math.max(0, sb.length() - n)); }
public String text() { return sb.toString(); }
}
public class AppendCommand implements Command {
private final TextBuffer buffer; private final String text;
public AppendCommand(TextBuffer b, String t) { buffer = b; text = t; }
public void execute() { buffer.append(text); }
public void undo() { buffer.chop(text.length()); }
}
public class Editor {
private final Deque<Command> history = new ArrayDeque<>();
private final Deque<Command> redoStack = new ArrayDeque<>();
public void run(Command c) { c.execute(); history.push(c); redoStack.clear(); }
public void undo() {
if (history.isEmpty()) return;
Command c = history.pop();
c.undo();
redoStack.push(c);
}
public void redo() {
if (redoStack.isEmpty()) return;
Command c = redoStack.pop();
c.execute();
history.push(c);
}
}
// Demo: e.run(new AppendCommand(buf, "sys")); e.run(new AppendCommand(buf, "-des")); e.undo();Explain without notes
Why does undo/redo need a stack, not a list?
Practice
Wrap a MovePiece command for Chess LLD with undo for take-back.
Trade-offs
- ↔
Commands multiply per operation type; receivers must expose fine-grained actions.
Completion checklist
I can build undo AND redo with two stacks and explain why a new command clears the redo stack.