Skip to main content

Command

Overview​

Encapsulate a request as an object, allowing parameterization, queuing, and undo support.

When to use​

  • You need undo/redo.
  • You want to queue or log operations.
  • You want the invoker to stay decoupled from the receiver that does the real work.

Java example​

interface Command {
void execute();
}

class Editor {
void save() {
System.out.println("saved");
}
}

class SaveCommand implements Command {
private final Editor editor;

SaveCommand(Editor editor) {
this.editor = editor;
}

public void execute() {
editor.save();
}
}

class Invoker {
void run(Command cmd) {
cmd.execute();
}
}

TypeScript example​

interface Command {
execute(): void;
}

class Editor {
save(): void {
console.log('saved');
}
}

class SaveCommand implements Command {
constructor(private editor: Editor) {}

execute(): void {
this.editor.save();
}
}

class Invoker {
run(cmd: Command): void {
cmd.execute();
}
}

Pros and cons​

Pros:

  • Supports undo/redo, queuing, and logging.
  • Decouples invoker from receiver.

Cons:

  • Many small classes.
  • Indirection can be heavy for simple actions.

Common pitfalls​

  • Not capturing all necessary state for undo.
  • Creating commands for trivial operations.