The Command pattern is a behavioral design pattern that we can use to turn a request into an object which contains all the information about the request.

The Command design pattern is quite popular in C#, especially when we want to delay or queue a request’s execution or when we want to keep track of our operations. Furthermore, this possibility to keep track of our operations gives us the opportunity to undo them as well.

The source code is available at the Command Design Pattern – Source Code.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

For the main page of this series check out C# Design Patterns.

Implementation of Command Design Pattern

The Command design pattern consists of the Invoker class, Command class/interface, Concrete command classes, and the Receiver class.  Having that in mind, in our example, we are going to follow the same design structure.

So, what we are going to do is write a simple app in which we are going to modify the price of the product that will implement the Command design pattern.

That being said, let’s start with the Product receiver class, which should contain the base business logic in our app:

public class Product
{
    public string Name { get; set; }
    public int Price { get; set; }

    public Product(string name, int price)
    {
        Name = name;
        Price = price;
    }

    public void IncreasePrice(int amount)
    {
        Price += amount;
        Console.WriteLine($"The price for the {Name} has been increased by {amount}$.");
    }

    public void DecreasePrice(int amount)
    {
        if(amount < Price)
        {
            Price -= amount;
            Console.WriteLine($"The price for the {Name} has been decreased by {amount}$.");
        }
    }

    public override string ToString() => $"Current price for the {Name} product is {Price}$.";
}

So this is our receiver class, which has a pretty straightforward logic. We just increase or conditionally decrease the product’s price. Finally, we have the ToString method, to be able to print our object.

Now the Client class can instantiate the Product class and execute the required actions. But the Command design pattern states that we shouldn’t use receiver classes directly. Instead, we should extract all the request details into a special class – Command.

And that is exactly what we are going to do.

The first thing we are going to do is to add the ICommand interface:

public interface ICommand
{
    void ExecuteAction();
}

Just to enumerate our price modification actions, we are going to add a simple PriceAction enumeration:

public enum PriceAction
{
    Increase,
    Decrease
}

Finally, let’s add the ProductCommand class:

public class ProductCommand : ICommand
{
    private readonly Product _product;
    private readonly PriceAction _priceAction;
    private readonly int _amount;

    public ProductCommand(Product product, PriceAction priceAction, int amount)
    {
        _product = product;
        _priceAction = priceAction;
        _amount = amount;
    }

    public void ExecuteAction()
    {
        if(_priceAction == PriceAction.Increase)
        {
            _product.IncreasePrice(_amount);
        }
        else
        {
            DecreasePrice(_amount);
        }
    }
}

As we can see, the ProductCommand class has all the information about the request and based on that executes required action.

To continue on, let’s add the ModifyPrice class, which will act as Invoker:

public class ModifyPrice
{
    private readonly List<ICommand> _commands;
    private ICommand _command;

    public ModifyPrice()
    {
        _commands = new List<ICommand>();
    }

    public void SetCommand(ICommand command) => _command = command;

    public void Invoke()
    {
        _commands.Add(_command);
        _command.ExecuteAction();
    }
}

This class can work with any command that implements the ICommand interface and store all the operations as well.

Now, we can start working with the client part:

class Program
{
    static void Main(string[] args)
    {
        var modifyPrice = new ModifyPrice();
        var product = new Product("Phone", 500);

        Execute(product, modifyPrice, new ProductCommand(product, PriceAction.Increase, 100));
           
        Execute(product, modifyPrice, new ProductCommand(product, PriceAction.Increase, 50));

        Execute(product, modifyPrice, new ProductCommand(product, PriceAction.Decrease, 25));

        Console.WriteLine(product);
    }

    private static void Execute(Product product, ModifyPrice modifyPrice, ICommand productCommand)
    {
        modifyPrice.SetCommand(productCommand);
        modifyPrice.Invoke();
    }
}

This should be our result:

Command design pattern - working solution

Excellent. We can see the order of our actions and the correct price after modifications.

Having in mind that we are keeping track of our actions in the Invoker class, we can use that to Undo our operations if we want to.

So, let’s try that.

Implementing Undo Operation in the Command Design Pattern

To implement the Undo operation let’s start with the ICommand interface modification:

public interface ICommand
{
    void ExecuteAction();
    void UndoAction();
}

Then, let’s modify the ProductCommand class by adding the UndoAction method:

public void UndoAction()
{
    if (_priceAction == PriceAction.Increase)
    {
        _product.DecreasePrice(_amount);
    }
    else
    {
        _product.IncreasePrice(_amount);
    }
}

Of course, we have to modify the ModifyPrice class as well by adding the UndoActions method:

public void UndoActions()
{
    foreach (var command in Enumerable.Reverse(_commands))
    {
        command.UndoAction();
    }
}

Please note that we are not using the Linq Reverse method but the Enumerable.Reverse() instead. That’s because the Linq method would mutate our list and we don’t want that. All we want is just a reversed list but without mutating the original list itself.

Now, when the Client class calls the UndoActions method, it will iterate through all the operations from the list and execute the opposite operation from the previously required.

Let’s try that:

class Program
{
    static void Main(string[] args)
    {
        var modifyPrice = new ModifyPrice();
        var product = new Product("Phone", 500);

        Execute(product, modifyPrice, new ProductCommand(product, PriceAction.Increase, 100));
          
        Execute(product, modifyPrice, new ProductCommand(product, PriceAction.Increase, 50));

        Execute(product, modifyPrice, new ProductCommand(product, PriceAction.Decrease, 25));

        Console.WriteLine(product);
        Console.WriteLine();

        modifyPrice.UndoActions();
        Console.WriteLine(product);
    }

    private static void Execute(Product product, ModifyPrice modifyPrice, ICommand productCommand)
    {
        modifyPrice.SetCommand(productCommand);
        modifyPrice.Invoke();
    }
}

The result:

Undo action - Command pattern

Everything works as it supposed to.

Improving the Solution

We have implemented the Command design pattern into our app, and there is nothing wrong with that. But there is one flaw in our solution which is not related to the Command pattern but to the business logic overall.

If we were to change the decreased amount from 25 to 2500 for example, what would happen? Well, we have the protection for that in the DecreasePrice method and it will not affect the result, and you are right. But it is going to affect the Undo actions.

Let’s see how:

...

Execute(product, modifyPrice, new ProductCommand(product, PriceAction.Decrease, 2500));

...

This is going to be the result:

Undo wrong result - command pattern

As you can see, our price hasn’t been decreased but the operation has been preserved in our store which caused the Undo action to fail.

So, let’s fix that.

The first thing we are going to do is to modify the DecreasePrice method in the Product class:

public bool DecreasePrice(int amount)
{
    if(amount < Price)
    {
        Price -= amount;
        Console.WriteLine($"The price for the {Name} has been decreased by {amount}$.");
        return true;
    }
    return false;
} 

Now, we can modify the ProductCommand class as well:

public class ProductCommand : ICommand
{
    private readonly Product _product;
    private readonly PriceAction _priceAction;
    private readonly int _amount;

    public bool IsCommandExecuted { get; private set; }

    public ProductCommand(Product product, PriceAction priceAction, int amount)
    {
        _product = product;
        _priceAction = priceAction;
        _amount = amount;
    }

    public void ExecuteAction()
    {
        if(_priceAction == PriceAction.Increase)
        {
            _product.IncreasePrice(_amount);
            IsCommandExecuted = true;
        }
        else
        {
            IsCommandExecuted = _product.DecreasePrice(_amount);
        }
    }

    public void UndoAction()
    {
        if (!IsCommandExecuted)
            return;

        if (_priceAction == PriceAction.Increase)
        {
            _product.DecreasePrice(_amount);
        }
        else
        {
            _product.IncreasePrice(_amount);
        }
    }
}

And that is it. Now if we start our app with a decreased amount of 2500 the result would be correct:

finall solution - command pattern

Great job.

Conclusion

Even though the Command design pattern introduces complexity to our code, it can be very useful.

With it, we can decouple classes that invoke operations from classes that perform these operations. Additionally, if we want to introduce new commands, we don’t have to modify existing classes. Instead, we can just add those new command classes to our project.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!