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:
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.