update on   5 min read

Command Design patterns

As a part of this article , I will explain about builder design pattern & what problem it solves?

Intro

The Command pattern allows you to represent operations as standalone objects. This gives your system flexibility, lets you manage requests in a uniform way, and enables powerful features like undo/redo, logging, and task scheduling—all while keeping the requesting code and the executing code independent of each other.

Core components in Command Design Pattern

  1. Command Interface: Declares an interface for all command classes. It usually has an execute() method.
  2. Concrete Command: Implements the Command interface and binds a receiver object to an action. It encapsulates the receiver object and invokes the corresponding operation on it when its execute() method is called.
  3. Receiver: An object that knows how to perform the actual operation. It is the target of the command.
  4. Invoker: An object that holds and asks the command to carry out the request. It doesn’t know anything about the concrete command or the receiver of the action. It simply has a way to execute the command.
  5. Client: Creates concrete command objects and sets their receiver.

Which Solid Priciple implemented in this Pattern?

  • SRP is the primary SOLID principle here — each class has a single, well-defined responsibility.
  • OCP is a natural side effect — you can extend behavior by adding new commands without touching existing code.

Real-World Analogy

  • A customer comes to hotel and try to give an order
  • The waiter (invoker) takes your order ( command object) and pass to kitchen (receiver)
  • The waiter doesn’t know about how the chief cooks
  • The order can be queued, modified, cancelled or repeated with outchanges the waiter process

UML Diagram

My local photo

Simple Command Pattern

Purpose

This solution implements a command-based banking system where financial transactions (deposits and withdrawals) on an account can be executed, tracked, and reversed in a reliable and structured manner. The design uses the Command Pattern to encapsulate transaction logic, enabling features like undo/redo, transaction grouping, and auditability.

GitHub Repository

Core Business Rules and Logic

1. Account Management

  • Object: Account

  • Responsibilities:

    • Maintains the account balance and applies an overdraft limit for withdrawals.
    • Provides methods for depositing funds (increasing balance) and withdrawing funds (reducing balance), with validation against the overdraft policy.
    • Exposes current balance for display or auditing purposes.
  • Business Rule Details:

    • Any deposit directly increases the balance. Deposit:
    • A withdrawal only succeeds if the resulting balance does not violate the overdraft limit. Withdraw:
    • Balance Visibility: The current balance is accessible (read-only) at any time for reporting.

2. Transaction Encapsulation (Command Pattern)

  • Components: , ICommand``BankAccountCommand

  • Responsibilities:

    • Encapsulates each banking operation (deposit or withdrawal) in a separate command object.
      • Each command knows how to execute its operation and how to undo it—enabling features like transaction reversal.
      • Records the execution state of each command for reliable undo/redo operations.
  • Business Rule Details:

    • Command Creation: Each operation (either deposit or withdraw) is wrapped within a command that stores the type of action, the target account, and the transaction amount.
      • Execution: Calling on a command performs the transaction on the account. Execute
      • Undo: Calling on the command reverses the performed action (withdraw undoes a deposit and vice versa), only if the command was executed successfully. Undo

3. Batch Processing and Transaction History

  • Component: Main program logic () Program.cs

  • Responsibilities:

    • Creates a series of commands representing a batch of transactions.
      • Executes all transactions sequentially.
      • Allows transactions to be reversed (undone) in reverse order, preserving the integrity of the account’s state.
  • Business Rule Details:

    • Batch Execution: All commands in a list are executed on a single account, updating the balance step by step.
      • Undo Mechanism: By reversing through the command history and calling , all transactions can be rolled back to their original state, supporting audit trails and error correction. Undo

Code Explaination

Command Interface

  • Component: interface (in ICommand.cs) ICommand
  • Role: Declares the contract for command objects ( and methods). Execute``Undo
public interface ICommand
{
void Execute();
void Undo();
}

Concrete Command

  • Component: class (in ICommand.cs) BankAccountCommand
  • Role: Implements the interface, encapsulating a request to perform deposit or withdrawal on an account. ICommand
public class BankAccountCommand : ICommand
{
private readonly Account _account;
private readonly ActionType _actionType;
private readonly int _amount;
private bool _isExecuted;
public enum ActionType
{
Deposit,
Withdraw
}
public BankAccountCommand(Account account,
ActionType actionType,
int amount)
{
_account = account;
_actionType = actionType;
_amount = amount;
}
public void Execute()
{
switch (_actionType)
{
case ActionType.Deposit:
_account.Deposit(_amount);
_isExecuted=true;
break;
case ActionType.Withdraw:
_isExecuted=_account.Withdraw(_amount);
break;
default:
break;
}
}
public void Undo()
{
if (!_isExecuted) return;
switch (_actionType)
{
case ActionType.Deposit:
_isExecuted= _account.Withdraw(_amount);
break;
case ActionType.Withdraw:
_account.Deposit(_amount);
_isExecuted=true;
break;
default:
break;
}
}
}

Receiver

  • Component: class (in Account.cs) Account
  • Role: Performs the actual business logic: deposit and withdraw money. The command delegates the actual work to this receiver.
public class Account
{
private int _balance;
private readonly int _overdDraftLimit;
public void Deposit(int amount)
{
_balance += amount;
WriteLine($"Deposit amount ${amount} ");
WriteLine($"Balance is ${_balance}");
}
public bool Withdraw(int amount)
{
if (_balance - _overdDraftLimit < amount) return false;
_balance -= amount;
WriteLine($"Withdraw amount ${amount}");
WriteLine($"Balance is ${_balance}");
return true;
}
public int GetBalance => _balance;
}

Invoker

  • Component: The code in Program class that loops through the list of commands and invokes and (in Program.cs) Execute()``Undo()
  • Role: Initiates execution or reversal of commands without knowing their details.
foreach (var cmd in command)
{
cmd.Execute();
}

Client

  • Component: The code in Main method that creates the , instantiates the objects, and prepares the list of commands (in Program.cs) Account``BankAccountCommand
  • Role: Sets up everything: creates the commands, sets up the receiver (account), and hands over the commands to the invoker logic.
internal static class Program
{
private static void Main(string[] args)
{
var account = new Account();
var command = new List<BankAccountCommand>
{
new BankAccountCommand(account, BankAccountCommand.ActionType.Deposit, 100),
new BankAccountCommand(account, BankAccountCommand.ActionType.Withdraw, 500),
};
WriteLine(account.GetBalance);
foreach (var cmd in command)
{
cmd.Execute();
}
WriteLine(account.GetBalance);
WriteLine("Reverse order");
foreach (var cmd in Enumerable.Reverse(command))
{
cmd.Undo();
}
WriteLine(account.GetBalance);
}
}
Share:
Back to Blog

Related Posts

View All Posts »