Command vs Strategy pattern

Posted by : on

Category : C#

Introduction

Some time ago, I saw a piece of code that looked something like this:

public class Server
{
   public ICommand? Command { get; set; }

   public void Run() => Command?.Execute();
}

public interface ICommand
{
   void Execute();
}

public class OperationACommand : ICommand
{
   private readonly OperationA _operationA = new();
   
   public void Execute() => _operationA.DoSomethingFromA();
}

public class OperationBCommand : ICommand
{
   private readonly OperationB _operationB = new();
   
   public void Execute() => _operationB.DoSomethingFromB();
}

public class OperationA
{
   public void DoSomethingFromA() => Console.WriteLine("Doing something from A");
}

public class OperationB
{
   public void DoSomethingFromB() => Console.WriteLine("Doing something from B");
}

This piece of code is an abomination.

Let me explain why: If you check the dependencies of the code above, you will notice that this actually is the strategy pattern. Simply renaming the abstract class/interface of the strategy to ICommand and the concrete strategies to commands, that doesn’t mean that we have the command pattern.

The above code will confuse anyone who tries to read it, because by seeing the ICommand interface, will expect that the command pattern is being used, naturally he will think that there is a class that plays the role of the Invoker class, until he actually opens and reads the implementation code of all the classes involved, where eventually, he will realize that the strategy pattern is implemented with wrong naming conventions.

The strategy pattern

Here is the dependency diagram of the above code:

Wrong Command implementation

This is actually the strategy pattern and its implementation is pretty straightforward:

By using an abstraction, we can change the code that gets executed, depending on the value of our field that is the type of the abstraction. In this example by changing the value of the Command property in the Server class, a different piece of code will be executed in the Run method.

The OperationACommand and OperationBCommand, are actually concrete strategies. They have code that gets executed, that either does something or calls code from other classes. But that doesn’t change anything, we still have the strategy pattern.

A simple execution would look like:

Server server = new();
server.Command = new OperationACommand();
server.Run();
server.Command = new OperationBCommand();
server.Run();

and the result would be:

Doing something from A
Doing something from B

In this example, the coder should have named the ICommand interface IStrategy, or even IOperation that has another method name, for example Perform, or anything else actually, except the naming convention we use when we have the Command pattern.

Let’s see now the Command pattern and how it is different from the Strategy pattern:

The command pattern

The Command pattern adds a class between the class that uses the command (in this case the Server class) and the abstraction (in this case the ICommand class). With this, the Server is decoupled from our commands and knows nothing about them. Now, it only depends on this class (called the Invoker).

In code the Invoker in our example could look like this:

public class Invoker
{
   public ICommand? Command { get; set; }

   public void Perform() => Command?.Execute();
}

and by getting the responsibility of the command knowledge from the Server class, the Server class will look like this:

public class Server
{
   private readonly Invoker _invoker;
   public Server(Invoker invoker) => _invoker = invoker;

   public void Run() => _invoker.Perform();
}

Simple commands

Just by adding the Invoker class and with the changes in the Server class, the equivalent code from the strategy execution example will be:

Invoker invoker = new();
Server server = new(invoker);
invoker.Command = new OperationACommand();
server.Run();
invoker.Command = new OperationBCommand();
server.Run();

In fact, the code from OperationA and OperationB methods could be in the concrete commands themselves, but now, our commands can have logic that can execute multiple methods from OperationA and OperationB or accept different objects as parameters.

Complex commands

Let’s say for example that OperationB is like this:

public class OperationB
{
   private readonly string _message;
   public OperationB(string message) => _message = message;

   public void DoSomethingFromB() => Console.WriteLine("Doing something from B with message: " + _message);
   public void DoSomethingElseFromB() => Console.WriteLine("Doing something else from B");
}

Then we would code the OperationBCommand like this:

public class OperationBCommand : ICommand
{
   private readonly OperationB _operationB;
   public OperationBCommand(OperationB operationB) => _operationB = operationB;

   public void Execute()
   {
      _operationB.DoSomethingFromB();
      _operationB.DoSomethingElseFromB();
   }
}

now the following is possible:

Invoker invoker = new();
Server server = new(invoker);
OperationB oneOperationB= new("Hello world!");
invoker.Command = new OperationBCommand(oneOperationB);
server.Run();
OperationB anotherOperationB= new("Hello again!");
invoker.Command = new OperationBCommand(anotherOperationB);
server.Run();

And the result would be:

Doing something from B with message: Hello world!
Doing something else from B
Doing something from B with message: Hi again!
Doing something else from B

With that, let’s see the benefits we can have from the command pattern:

Benefits of the Command pattern

The Command pattern may seem more complicated than the strategy, for simple commands, but when we want more than a simple execution, it actually provides boilerplate code that gets more exotic things done easily compared to the changes that we would have to do with the strategy pattern:

Decoupling of the commands

As we saw before, our commands are now decoupled from the Server that executes them. The only thing we have to do, is create a Server with its Invoker and call its Run method.

No matter how many different commands we create, the server doesn’t care because knows nothing about commands, it tells the invoker through its Run method, to execute the invoker’s Perform method. All this while another part of our code, is responsible to tell the Invoker which command should be next by setting its Command property.

Many to one relationship

Because another piece of our code is responsible, for assigning values to the Command property, the Invoker can have a collection that holds those commands and each one gets executed, whenever the Server can.

We can have many incoming commands in a period T ms, but our server can run only one command every T ms. By holding these commands in a collection in the invoker class, this is easily done without having to change the Server class:

public class Invoker
{
   private readonly Queue<ICommand> _commands = new();
   public ICommand? Command
   {
      get
      {
         _commands.TryDequeue(out var command);
         return command;
      }
      set
      {
         if(value is not null)
            _commands.Enqueue(value);
      }
   }

   public void Perform() => Command?.Execute();
}

so now we can do this:

Invoker invoker = new();
Server server = new(invoker);
OperationB oneOperationB= new("Hello world!");
OperationB anotherOperationB= new("Hi again!");
invoker.Command = new OperationBCommand(oneOperationB);
invoker.Command = new OperationBCommand(anotherOperationB);
server.Run();
server.Run();
server.Run();
invoker.Command = new OperationBCommand(oneOperationB);
invoker.Command = new OperationBCommand(anotherOperationB);
invoker.Command = new OperationBCommand(anotherOperationB);
invoker.Command = new OperationBCommand(anotherOperationB);
server.Run();
server.Run();
server.Run();

and the result would be:

Doing something from B with message: Hello world!
Doing something else from B
Doing something from B with message: Hi again!
Doing something else from B
Doing something from B with message: Hello world!
Doing something else from B
Doing something from B with message: Hi again!
Doing something else from B
Doing something from B with message: Hi again!
Doing something else from B

If we wanted to do that with the strategy pattern, all the logic about the collection of the commands would have to be inside the Server class. That would start to get messy, because it is not the responsibility of the Server to have a collection of commands to execute, but its responsibility is to only execute one command when it is able.

What would be even more difficult to change would be the following scenario:

Many to many relationship

We have so many incoming commands that we decide that we need another Server class to execute those commands. If the Server class would have been responsible for keeping the collection of the commands, like having the strategy pattern that gets its strategies from a collection, then we would need a mechanism to have these collections synchronized between our two Server objects.

Now, because we have implemented everything with the command pattern and the Invoker class is responsible for the collection of the commands, no change is needed anywhere. We just add a new Server and everything works as expected:

Invoker invoker = new();
Server server = new(invoker);
Server server2 = new(invoker);
OperationB oneOperationB= new("Hello world!");
OperationB anotherOperationB= new("Hi again!");
invoker.Command = new OperationACommand();
invoker.Command = new OperationBCommand(oneOperationB);
invoker.Command = new OperationBCommand(anotherOperationB);
server.Run();
server2.Run();
server.Run();
server2.Run();
invoker.Command = new OperationACommand();
invoker.Command = new OperationBCommand(oneOperationB);
invoker.Command = new OperationBCommand(anotherOperationB);
invoker.Command = new OperationACommand();
invoker.Command = new OperationBCommand(anotherOperationB);
invoker.Command = new OperationBCommand(oneOperationB);
server.Run();
server2.Run();
server.Run();
server2.Run();
server.Run();
server2.Run();

This code’s result is:

Doing something from A
Doing something from B with message: Hello world!
Doing something else from B
Doing something from B with message: Hi again!
Doing something else from B
Doing something from A
Doing something from B with message: Hello world!
Doing something else from B
Doing something from B with message: Hi again!
Doing something else from B
Doing something from A
Doing something from B with message: Hi again!
Doing something else from B
Doing something from B with message: Hello world!
Doing something else from B

Conclusion

I hope this posts, clarifies the differences between the command and strategy patterns. The command pattern is not only useful for implementing undo/redo functionality.

Although strategy is simpler, as it is a simple use of polymorphism, it can get much more complicated than the command pattern in certain situations, because the command pattern encapsulates the operations as commands and decouples the Server class from the operations and the commands, by adding between them an Invoker class. Now we can set the commands to the invoker class from anywhere in our code, without this piece of code to have knowledge of our Server class.

I hope you found this post useful. Thank you for reading and as always, if you have any questions or comments you can use the comments section or contact me directly via the contact form or by email, also if you don’t want to miss any of the new blog posts, you can always subscribe to my newsletter or the RSS feed.


Follow me: