Command
Encapsulate a request as an object for queuing, logging, and undoable operations.
Normally you call a method and it runs immediately. Sometimes that is not enough.
You may need to queue the action for later, undo it, log it, or retry it after a failure. You cannot do any of that with a plain method call, because once it runs there is nothing left to hold.
Command turns the action into an object. Now it can be stored in a list, passed around, saved, and executed whenever you choose.
What the interviewer is probing.
1. "What does Command encapsulate?" *Probing:* the purpose. *Stalls:* "A method." *Moves up:* a request as an object, with its parameters, so it can be queued, logged, retried or undone.
2. "What capability makes it distinctive?" *Probing:* the value. *Stalls:* "Nothing." *Moves up:* undo and redo, by pairing each command with its inverse and keeping a history.
3. "Where does it appear in distributed systems?" *Probing:* the breadth. *Stalls:* "Nowhere." *Moves up:* a message on a queue is a command object serialised — which is why the pattern underpins task queues and event sourcing.
4. "What is the cost?" *Probing:* the trade. *Stalls:* "None." *Moves up:* a class per operation, which is noise unless you actually need queuing, logging or undo.
A restaurant order slip — the waiter hands the slip to the kitchen. Slips can be queued or cancelled.
Key Concepts
public interface Command {
void execute();
void undo();
}
public class InsertTextCommand implements Command {
private final TextEditor editor;
private final String text;
private final int pos;
public InsertTextCommand(TextEditor e, String t, int p) {
this.editor = e; this.text = t; this.pos = p;
}
public void execute() { editor.insert(text, pos); }
public void undo() { editor.delete(pos, text.length()); }
}
public class History {
private final Deque<Command> stack = new ArrayDeque<>();
public void execute(Command c) { c.execute(); stack.push(c); }
public void undo() { if (!stack.isEmpty()) stack.pop().undo(); }
}