behavioral

Command

Encapsulate a request as an object so it can be invoked, queued, logged, or undone independently of the receiver that performs the work.

Problem

behavioral

A system needs to trigger actions without tightly coupling the code that requests an operation to the code that performs it, and it may also need queuing, history, or undo support.

Integration notes

Commands work well for UI actions, background jobs, workflow steps, and undoable operations because invokers can trigger commands without depending on receiver details.

Tradeoffs

  • Introduces extra classes or objects for each action.
  • Can feel heavier than direct method calls when the workflow is simple.
  • Makes requests more flexible, loggable, and replayable.

Languages

typescript, java, python, angular, react, react-native, csharp, dotnet

Platforms

frontend, backend, integration

Variants

frontend

Undoable command

typescript

Model user actions as reversible commands so they can be executed, undone, and redone.

Intent: Support edit history and reversible user interaction.

Problem: Undo logic becomes tangled when state changes happen directly in UI handlers.

Solution: Wrap each action in a command object that knows how to execute and undo itself.

Dependencies

command

Related variants

command-queuedcommand-macro

Examples

command

Best for editors, design tools, and any interactive surface with history controls.

Scenarios

Text editor undo

A text editor wraps insert operations in command objects so actions can be executed and later undone from command history.

Context: An editing tool needs a reliable way to reverse user actions and replay them in order.

Problem: Direct method calls make undo and redo logic tangled with the editor state.

Solution: Use Command to wrap each edit as an object that can be executed and reversed.

frontend

Language examples

Core languages

Frameworks and libraries

Text editor undotypescript

Wrap edits as commands so the editor can execute them and later undo the most recent action.

TypeScript
interface Command {
  execute(): void;
  undo(): void;
}

class InsertTextCommand implements Command {
  constructor(
    private editor: Editor,
    private text: string,
  ) {}

  execute() {
    this.editor.insert(this.text);
  }

  undo() {
    this.editor.delete(this.text.length);
  }
}

class Editor {
  private content = "";

  insert(text: string) {
    this.content += text;
  }

  delete(length: number) {
    this.content = this.content.slice(0, -length);
  }

  getText() {
    return this.content;
  }
}

class CommandHistory {
  private commands: Command[] = [];

  execute(command: Command) {
    command.execute();
    this.commands.push(command);
  }

  undoLast() {
    const command = this.commands.pop();
    if (command) command.undo();
  }
}

const editor = new Editor();
const history = new CommandHistory();

history.execute(new InsertTextCommand(editor, "Hello "));
history.execute(new InsertTextCommand(editor, "world"));
history.undoLast();

Real-world examples

  • Undo and redo systems: Editors and design tools often wrap changes as commands so actions can be reversed from command history.
  • Background job queues: Applications can enqueue commands for email, reporting, or deployment tasks and execute them later in workers.
  • UI and device controls: Buttons, menu actions, and remote controls can trigger commands without depending directly on the receivers they control.