Command turns an action into an object. That sounds simple, but it enables powerful capabilities:

  • queueing
  • retries
  • auditing
  • delayed execution
  • undo in some domains

Example Problem

An admin console can trigger order operations:

  • approve order
  • cancel order
  • resend invoice

These actions should be executable now or later through the same abstraction.


UML

classDiagram
    class OrderCommand {
      <<interface>>
      +execute()
    }
    class ApproveOrderCommand
    class CancelOrderCommand
    class CommandBus
    OrderCommand <|.. ApproveOrderCommand
    OrderCommand <|.. CancelOrderCommand
    CommandBus --> OrderCommand

Implementation Walkthrough

public interface OrderCommand {
    void execute();
}

public final class OrderOperations {
    public void approve(String orderId) {
        System.out.println("Approved " + orderId);
    }

    public void cancel(String orderId) {
        System.out.println("Cancelled " + orderId);
    }
}

public final class ApproveOrderCommand implements OrderCommand {
    private final OrderOperations operations;
    private final String orderId;

    public ApproveOrderCommand(OrderOperations operations, String orderId) {
        this.operations = operations;
        this.orderId = orderId;
    }

    public void execute() {
        operations.approve(orderId);
    }
}

public final class CancelOrderCommand implements OrderCommand {
    private final OrderOperations operations;
    private final String orderId;

    public CancelOrderCommand(OrderOperations operations, String orderId) {
        this.operations = operations;
        this.orderId = orderId;
    }

    public void execute() {
        operations.cancel(orderId);
    }
}

public final class CommandBus {
    public void submit(OrderCommand command) {
        command.execute();
    }
}

Usage:

OrderOperations operations = new OrderOperations();
CommandBus commandBus = new CommandBus();
commandBus.submit(new ApproveOrderCommand(operations, "ORD-200"));

This version executes immediately, but the abstraction is already carrying the right shape for more advanced behavior. Once the action is a first-class object, the system can attach metadata such as requester identity, retry count, scheduled execution time, or audit correlation without redesigning every call site.


Why This Pattern Matters

If actions are plain method calls, delayed execution and audit trails require ad hoc work. With Command, the action itself is a first-class unit.

That makes it easier to store metadata such as:

  • who requested it
  • when it should run
  • how many retries are allowed

This is why Command appears frequently in job systems and workflow engines.

That is the practical lens for the pattern: use it when the action needs to outlive the current method stack frame.