Full Stack • Java • System Design • Cloud • AI Engineering

Command Design Pattern in Java

Learn Command Design Pattern in Java with undo/redo operations, task queues, workflow automation, Spring examples, microservices use cases, UML diagrams, code examples, and interview questions.

What You Will Learn

In this article, you'll learn:

  • What is Command Pattern?
  • Why Command Pattern is Needed
  • Command Pattern Architecture
  • Undo and Redo Operations
  • Queue Processing
  • Workflow Automation
  • Java Implementation
  • Spring Framework Examples
  • Microservices Use Cases
  • Benefits and Limitations
  • Interview Questions

Introduction

Imagine you are building:

Banking Application

E-Commerce System

Workflow Engine

Task Scheduler

Users perform actions:

Transfer Money

Place Order

Approve Loan

Send Notification

Without Command Pattern:

button.transferMoney();

button.placeOrder();

button.sendEmail();

The caller becomes tightly coupled to business logic.

Command Pattern solves this problem.


What is Command Pattern?

Command is a Behavioral Design Pattern that encapsulates a request as an object.

Instead of calling methods directly:

Caller

↓

Command Object

↓

Receiver

The request becomes an object.


Purpose of Command Pattern

Primary goal:

Encapsulate Requests

As Objects

Benefits:

Queue Requests

Schedule Requests

Undo Requests

Log Requests

Retry Requests

Real World Analogy

Think about a restaurant.

Customer:

Places Order

Waiter:

Takes Order

Chef:

Prepares Food

The waiter does not cook food.

The waiter only carries the order.

The order acts as a:

Command Object

Restaurant Workflow

flowchart LR

Customer --> Waiter

Waiter --> Order

Order --> Chef

Problem Without Command Pattern

flowchart LR

Client --> PaymentService

Client --> NotificationService

Client --> ReportService

Client --> AuditService

Client knows too much.

High coupling.


Solution With Command Pattern

flowchart LR

Client --> Command

Command --> Receiver

Client only executes commands.


Command Pattern Architecture

flowchart LR

Client

--> Invoker

Invoker

--> Command

Command

--> Receiver

Key Components

Command

Interface representing an action.


Concrete Command

Actual implementation of action.


Receiver

Performs business logic.


Invoker

Executes commands.


Client

Creates commands.


UML Diagram

classDiagram

class Command {
    <<interface>>
    +execute()
}

class ConcreteCommand

class Receiver

class Invoker

Command <|.. ConcreteCommand

ConcreteCommand --> Receiver

Invoker --> Command

Banking Example

Money Transfer Request

Actors:

Customer

Transfer Command

Transfer Service

Step 1: Command Interface

public interface Command {

    void execute();
}

Step 2: Receiver

public class BankService {

    public void transferMoney(
            String from,
            String to,
            double amount) {

        System.out.println(
                "Transferred "
                        + amount
                        + " from "
                        + from
                        + " to "
                        + to);
    }
}

Step 3: Concrete Command

public class TransferMoneyCommand
        implements Command {

    private final BankService bankService;

    private final String from;

    private final String to;

    private final double amount;

    public TransferMoneyCommand(
            BankService bankService,
            String from,
            String to,
            double amount) {

        this.bankService = bankService;
        this.from = from;
        this.to = to;
        this.amount = amount;
    }

    @Override
    public void execute() {

        bankService.transferMoney(
                from,
                to,
                amount);
    }
}

Step 4: Invoker

public class CommandInvoker {

    public void invoke(
            Command command) {

        command.execute();
    }
}

Step 5: Client

public class CommandDemo {

    public static void main(
            String[] args) {

        BankService service =
                new BankService();

        Command command =
                new TransferMoneyCommand(
                        service,
                        "ACC100",
                        "ACC200",
                        5000);

        CommandInvoker invoker =
                new CommandInvoker();

        invoker.invoke(command);
    }
}

Output

Transferred 5000 from ACC100 to ACC200

Execution Flow

sequenceDiagram

Client->>Invoker: invoke(command)

Invoker->>Command: execute()

Command->>Receiver: transferMoney()

Receiver-->>Client: Success

Why Command Pattern?

Because commands become objects.

Objects can be:

Stored

Queued

Logged

Retried

Scheduled

Undo Operation Example

One of the biggest advantages.


Command Interface

public interface Command {

    void execute();

    void undo();
}

Transfer Command

@Override
public void undo() {

    bankService.transferMoney(
            to,
            from,
            amount);
}

Workflow

flowchart LR

Execute

--> SaveHistory

SaveHistory

--> Undo

Text Editor Example

Actions:

Insert Text

Delete Text

Copy Text

Paste Text

Each action becomes a command.


Undo Redo Flow

flowchart LR
    A[User Action]
    B[Command]
    C[History]
    D[Undo]
    E[Redo]

    A --> B
    B --> C
    C --> D
    D --> E

E-Commerce Example

Commands:

Place Order

Cancel Order

Ship Order

Refund Order

Each operation is a command.


Order Processing Flow

flowchart LR
    A[Order Request]
    B[Place Order Command]
    C[Order Service]

    A --> B
    B --> C

Loan Approval Example

Commands:

Submit Loan

Approve Loan

Reject Loan

Disburse Loan

Each action is independent.


flowchart LR
    A[Submit Application]
    B[Credit Check]
    C[Approval Command]
    D[Fund Transfer]

    A --> B
    B --> C
    C --> D

Task Queue Example

Commands can be queued.

Queue<Command> queue =
        new LinkedList<>();

Add commands:

queue.add(command1);
queue.add(command2);
queue.add(command3);

Process later.


Queue Processing Flow

flowchart LR

Queue

--> Command1

--> Command2

--> Command3

--> Execute

Batch Processing Example

Nightly jobs:

Generate Reports

Send Emails

Calculate Interest

Create Statements

Each task is a command.


Scheduler Example

scheduler.schedule(
        command,
        LocalDateTime.now()
                .plusHours(1));

Execute later.


Microservices Example

Commands can be published to Kafka.

OrderPlaced

PaymentCompleted

ShipmentCreated

Each event triggers a command.


Kafka Workflow

flowchart LR
    A[Producer]
    B[Kafka]
    C[Command Consumer]
    D[Business Service]

    A --> B
    B --> C
    C --> D

Spring Framework Example

Spring Batch internally follows Command-like behavior.

Each step:

Read

Process

Write

acts like a command.


Spring Scheduler Example

@Scheduled(
    fixedRate = 60000
)
public void executeJob() {

}

Scheduled jobs are command executions.


Quartz Scheduler Example

Job job =
        JobBuilder
                .newJob(
                        ReportJob.class)
                .build();

Job acts as command.


Real Enterprise Examples

Banking

Fund Transfer

Bill Payment

Interest Calculation

Insurance

Claim Approval

Policy Renewal

Premium Calculation

Retail

Place Order

Cancel Order

Return Order

Workflow Engines

Camunda

JBPM

Apache Airflow

Use command concepts heavily.


Benefits

✅ Decouples Sender and Receiver

✅ Supports Undo/Redo

✅ Supports Queuing

✅ Supports Scheduling

✅ Supports Logging

✅ Easy To Extend

✅ Follows Open Closed Principle


Limitations

❌ More Classes

❌ Additional Complexity

❌ Can Create Many Command Objects

❌ Overkill For Simple Applications


When To Use

Use Command Pattern when:

  • You need Undo/Redo
  • You need Request Queues
  • You need Scheduling
  • You need Workflow Automation
  • You need Retry Mechanisms

When Not To Use

Avoid when:

  • Actions are simple
  • No history is needed
  • No queueing or scheduling is required

Command vs Strategy

Feature Command Strategy
Purpose Encapsulate Request Encapsulate Algorithm
Focus Action Logic
Example Transfer Money Interest Calculation Strategy

Command vs Chain of Responsibility

Feature Command Chain
Purpose Execute Action Pass Request
Flow Single Action Multiple Handlers
Example Fund Transfer Validation Pipeline

Interview Questions

What is Command Pattern?

A behavioral pattern that encapsulates a request as an object.


Why Use Command Pattern?

To decouple sender and receiver and support undo, queueing, and scheduling.


Real World Example?

Restaurant Order System.


What is Receiver?

The object that performs actual business logic.


What is Invoker?

The object that executes commands.


Can Command Pattern Support Undo?

Yes. Commands can store state and implement undo().


Where Is Command Pattern Used?

Spring Batch, Quartz Scheduler, Workflow Engines, Kafka Consumers, and Enterprise Applications.


Key Takeaways

  • Command is a Behavioral Design Pattern.
  • Requests are represented as objects.
  • Supports Undo, Redo, Scheduling, and Queueing.
  • Decouples caller from business logic.
  • Widely used in Banking, Insurance, Retail, and Workflow Systems.
  • Powers task schedulers, workflow engines, and event-driven architectures.
  • One of the most useful patterns in enterprise Java development.