Design Patterns: Command

Characteristics

  • Command: The own command, that contains the instructions and references.
  • Receiver: The thing that the command will execute.
  • Invoker: Responsible to execute the commands.
  • Client: The beginning of all. It decides what command will execute.

Hands-On

Commands Implementation

public interface ICommand
{
void Execute();
bool CanExecute(); void Undo();
}
  • Execute(): to execute, in fact, the command
  • CanExecute(): some condition that we consider necessary to execute the command
  • Undo(): like rollback to the command
public class CommandManager
{
private Stack<ICommand> commands = new Stack<ICommand>();
public void Invoke(ICommand command)
{
if (command.CanExecute())
{
commands.Push(command);
command.Execute();
}
}
public void Undo()
{
while(commands.Count > 0)
{
var command = commands.Pop();
command.Undo();
}
}
}
public class AddClientCommand : ICommand
{
private readonly IClientRepository _clientRepository;
private readonly Client _client;
public AddClientCommand(IClientRepository clientRepository, Client client) =>
(_clientRepository, _client) = (clientRepository, client);
public bool CanExecute()
{
if (_client == null)
return false;
return _clientRepository.GetClient(_client.Id) == null;
}
public void Execute()
{
if (_client == null)
return;
_clientRepository.Add(_client);
}
public void Undo()
{
if (_client == null)
return;
_clientRepository.Remove(_client.Id);
}
}
  1. We receive, by constructor, all we need:
    1.1 The repository (IClientRepository), that we use to do some operation in the datastore
    1.2 And the Client object that we will use to do something
  2. The CanExecute() method: we inform that the condition to create a client is if this client does not exists.
  3. The Execute() method: we just verify if the client object is not null and create it.
  4. The Undo() method: it is a rollback method. So, in this case, we just exclude that client we created.

The execution

class Program
{
static void Main(string[] args)
{
IClientRepository clientRepository = default;
Client client = default;

var addClientCommand = new AddClientCommand(clientRepository, client);

var manager = new CommandManager();
manager.Invoke(addClientCommand);

// ... do something

manager.Undo();
}
}
  • First, we instantiate our Client Command, passing the repository and the object.
  • The AddClientCommand is of the ICommand type, so we can pass it to our CommandManager, to execute the command.
  • Finally, if we need to undo our process we can call the Undo() method, of the CommandManager

Conclusion

  • Allow you to make a separate responsibilities.
  • Make your application more robust.
  • Pay attention for you do not to put unnecessary complexity.

Bachelor in Computer Science, MBA in Software Architecture and .NET Developer.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Problem Solving in Programming

Learn Java in the simplest way — variables and methods

Accounts & Alpha Codes

Testing In Very Simple Words

Jailbreak iOS 14

Docker image for building TensorFlow Android demo app

API Development: Rest Vs GraphQL

Messing up words in passwords

Someone, maybe a woman, with a tablet computer that says “Save” with a green check mark after Save. The blue background has a darker blue shield above the word Save and a lighter blue cloud-like shape on the shield.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alex Alves

Alex Alves

Bachelor in Computer Science, MBA in Software Architecture and .NET Developer.

More from Medium

Setup your CI/CD pipeline with Configuration as a Code and GitHub Actions in 1 minute.

Repository Pattern for Data Access in Software Development

Repository Design Pattern — https://codingsight.com/entity-framework-antipattern-repository/

Microsoft .NET challenge France 2020 final

Publishing an artifact on Github Actions of a .Net 6 applications