MTI TEK
  • Home
  • About
  • LLMs
  • Docker
  • Kubernetes
  • Java
  • All Resources
Java Design Patterns | Command
  1. Overview and Definition
  2. Class Diagram
  3. Implementation Example
    • The Command Interface
    • The Concrete Commands
    • The Receiver
    • The Invoker
    • Testing the Command Pattern

  1. Overview and Definition
    The Command pattern is a behavioral design pattern that encapsulates a request as an object, thereby allowing you to parameterize clients with different requests, queue or log requests, and support undoable operations. It decouples the object that invokes the operation from the object that performs the operation.

    Key Components:
    • Command: Declares an interface for executing an operation and may include methods for undo functionality.
    • Concrete Command: Implements the Command interface and defines the binding between a Receiver object and an action.
    • Receiver: Knows how to perform the operations associated with carrying out a request.
    • Invoker: Asks the command to carry out the request without knowing the specifics of the operation.
    • Client: Creates a Concrete Command object and sets its receiver.

    Benefits:
    • Decoupling: Separates the object that requests an operation from the object that performs it.
    • Parameterization: Allows parameterizing objects with different requests and queuing operations.
    • Undo/Redo Support: Commands can implement undo functionality to reverse their effects.
    • Logging and Queuing: Commands can be stored, logged, or queued for later execution.
  2. Class Diagram
    Command Pattern Components:
    • Command: Transaction interface - defines the interface for executing operations.
    • Concrete Commands: DebitTransaction and CreditTransaction classes - encapsulate specific operations with their parameters.
    • Receiver: Account class - knows how to perform the actual business operations.
    • Invoker: TransactionProcessor class - requests commands to execute without knowing their specifics.
    ┌─────────────────────────────┐
    │       <<interface>>         │
    │        Transaction          │  ← Command
    ├─────────────────────────────┤
    │ + execute(): void           │
    │ + undo(): void              │
    └─────────────────────────────┘
                  △
                  │ implements
                  │
    ┌──────────────────┬───────────────────┐
    │  DebitTransaction│ CreditTransaction │  ← Concrete Commands
    ├──────────────────┼───────────────────┤
    │- account: Account│- account: Account │
    │- amount: double  │- amount: double   │
    │+ execute()       │+ execute()        │
    │+ undo()          │+ undo()           │
    └──────────────────┴───────────────────┘
    
    
    ┌─────────────────────────────┐
    │          Account            │  ← Receiver
    ├─────────────────────────────┤
    │ - balance: double           │
    │ + debit(double): void       │
    │ + credit(double): void      │
    │ + getBalance(): double      │
    └─────────────────────────────┘
    
    
    ┌─────────────────────────────────────────┐
    │          TransactionProcessor           │  ← Invoker
    ├─────────────────────────────────────────┤
    │ + processTransaction(Transaction): void │
    └─────────────────────────────────────────┘
                    
  3. Implementation Example
    • The Command Interface:
      The Command interface declares methods for executing operations and potentially undoing them. All concrete commands implement this interface to provide consistent behavior.
      public interface Transaction {
          void execute();
          void undo();
      }
    • The Concrete Commands:
      Concrete Commands implement the Command interface and encapsulate specific operations with their parameters. They maintain a reference to the receiver and invoke its methods to perform the actual work.

      Debit Transaction Command:
      public class DebitTransaction implements Transaction {
          private Account account;
          private double amount;
      
          public DebitTransaction(Account account, double amount) {
              this.account = account;
              this.amount = amount;
          }
      
          public void execute() {
              account.debit(amount);
          }
      
          public void undo() {
              account.credit(amount);
          }
      }
      Credit Transaction Command:
      public class CreditTransaction implements Transaction {
          private Account account;
          private double amount;
      
          public CreditTransaction(Account account, double amount) {
              this.account = account;
              this.amount = amount;
          }
      
          public void execute() {
              account.credit(amount);
          }
      
          public void undo() {
              account.debit(amount);
          }
      }
    • The Receiver:
      The Receiver knows how to perform the operations associated with carrying out requests. It contains the business logic that the commands will invoke.
      public class Account {
          private double balance;
      
          public Account(double initialBalance) {
              this.balance = initialBalance;
          }
      
          public void debit(double amount) {
              balance -= amount;
              System.out.println("Debited: " + amount + ", Balance: " + balance);
          }
      
          public void credit(double amount) {
              balance += amount;
              System.out.println("Credited: " + amount + ", Balance: " + balance);
          }
      
          public double getBalance() {
              return balance;
          }
      }
    • The Invoker:
      The Invoker asks the command to carry out the request without knowing the specifics of the operation. It provides a simple interface for executing commands and can support additional features like command history.
      public class TransactionProcessor {
          public void processTransaction(Transaction transaction) {
              System.out.println("Processing transaction...");
              transaction.execute();
          }
      
          public void undoTransaction(Transaction transaction) {
              System.out.println("Undoing transaction...");
              transaction.undo();
          }
      }
    • Testing the Command Pattern:
      The client code demonstrates how commands encapsulate operations and can be executed and undone. It shows the decoupling between the invoker and the specific operations being performed.
      public class CommandPatternTest {
          public static void main(String[] args) {
              // Create the receiver
              Account account = new Account(1000.0);
      
              // Create concrete commands
              Transaction debitTransaction = new DebitTransaction(account, 200.0);
              Transaction creditTransaction = new CreditTransaction(account, 150.0);
      
              // Create the invoker
              TransactionProcessor processor = new TransactionProcessor();
      
              System.out.println("Initial Balance: " + account.getBalance());
      
              // Execute transactions
              processor.processTransaction(debitTransaction);
              processor.processTransaction(creditTransaction);
      
              System.out.println("After Transactions");
      
              // Undo transactions
              processor.undoTransaction(creditTransaction);
              processor.undoTransaction(debitTransaction);
      
              System.out.println("Final Balance: " + account.getBalance());
          }
      }
© 2025 mtitek