C# - Implementando o padrão Command


Neste artigo veremos um exemplo de implementação do padrão Command na linguagem C#.

Para mais detalhes sobre esse padrão consulte o meu artigo: .NET - O padrão de projeto Command

O padrão de projeto Command é constituído dos objetos :

  1. Invoker (Chamador)
  2. Command (Comando e ComandoConcreto)
  3. Receiver (Receptor)
  4. Client (Cliente)

Vamos fazer a implementação desse padrão seguindo esta estrutura.

Criando o projeto Console no Visual Studio 2019

Abra o VS 2019 e crie um novo projeto do tipo Console usando o .NET Core com o nome CShp_Command.

Vamos criar uma pasta chamada Command onde vamos definir a implementação do padrão.

Na pasta Command crie a classe Produto no projeto que fará o papel de Receptor ou Receiver:

using System;
namespace CShp_Command.Command
{
    public class Produto
    {
        public string Nome { get; set; }
        public int Preco { get; set; }

        public Produto(string nome, int preco)
        {
            Nome = nome;
            Preco = preco;
        }
        public void AumentarPreco(int valor)
        {
            Preco += valor;
            Console.WriteLine($"O preço do produto {Nome} aumentou em  R$ {valor}.");
        }
        public void DiminuirPreco(int valor)
        {
            if (valor < Preco)
            {
                Preco -= valor;
                Console.WriteLine($"O preco do produto {Nome} diminuiu em R$ {valor}.");
            }
        }
        public override string ToString() => $"O preço atual do produto {Nome} é R$ {Preco}.";
    }
}

Esta classe faz o papel de Receiver e possui os métodos para aumentar e diminuir o preço de um Produto e sobrescrever o método ToString() para exibir o objeto.

O padrão Command estabelece que não devemos usar as classes receptoras diretamente, por isso vamos obter os detalhes da solicitação a partir da classe Command.

Crie uma interface chamada ICommand na pasta Command:

    public interface ICommand
    {
        void ExecutarAcao();
    }

Nesta interface definimos o método ExecutarAcao() que deverá ser implementado.

Para realizar a enumeração das ações: aumentar e diminuir preço, crie uma enumeração chamada PrecoAcao:

    public enum PrecoAcao
    {
        Aumentar,
        Diminuir
    }

Agora vamos criar a classe Command chamada ProdutoCommand que vai implementar interface ICommand:

    public class ProdutoCommand : ICommand
    {
        private readonly Produto _produto;
        private readonly PrecoAcao _precoAcao;
        private readonly int _valor;
        public ProdutoCommand(Produto produto, PrecoAcao precoAcao, int valor)
        {
            _produto = produto;
            _precoAcao = precoAcao;
            _valor = valor;
        }
        public void ExecutarAcao()
        {
            if(_precoAcao == PrecoAcao.Aumentar)
            {
                _produto.AumentarPreco(_valor);
            }
            else
            {
                _produto.DiminuirPreco(_valor);
            }
        }
    }

Esta classe possui todas as informações para executar as ações e aumentar e diminuir o preço.

Vamos criar a classe ModificarPreco:

using System.Collections.Generic;
namespace CShp_Command.Command
{
    public class ModificarPreco
    {
        private readonly List<ICommand> _commands;
        private ICommand _command;
        public ModificarPreco()
        {
            _commands = new List<ICommand>();
        }
        public void SetCommand(ICommand command) => _command = command;
        public void Invoke()
        {
            _commands.Add(_command);
            _command.ExecutarAcao();
        }
    }
}

Esta classe trabalha com qualquer comando que implementa a interface ICommand e armazena todas as operações.   

Na figura abaixo vemos os artefatos criados no projeto:

Agora é só alegria... vamos testar...

using CShp_Command.Command;
using System;
namespace CShp_Command
{
    class Program
    {
        static void Main(string[] args)
        {
            var modificarPreco = new ModificarPreco();
            var produto = new Produto("Tablet", 900);
            Execute(produto, modificarPreco, new ProdutoCommand(produto, PrecoAcao.Aumentar, 95));
            Execute(produto, modificarPreco, new ProdutoCommand(produto, PrecoAcao.Aumentar, 60));
            Execute(produto, modificarPreco, new ProdutoCommand(produto, PrecoAcao.Diminuir, 45));
            Console.WriteLine(produto);
        }
        private static void Execute(Produto produto, ModificarPreco modificarPreco, ICommand produtoCommand)
        {
            modificarPreco.SetCommand(produtoCommand);
            modificarPreco.Invoke();
        }
    }
}

Criamos uma instância da classe ModificarPreco() e a seguir criamos um novo Produto.

A seguir invocamos o método Execute onde passamos o produto, a instância de ModificarPreco e o command.

Abaixo vemos o resultado da execução do projeto:

O resultado acima mostra a execução dos comandos implementados para aumentar e diminiur os preços a partir da interface ICommand.

Pegue a solução completa aqui: CShp_Command.zip

"Então, aproximando-se dele um escriba, disse-lhe: Mestre, seguir-te-ei para onde quer que fores.
Mas Jesus lhe respondeu: As raposas têm seus covis, e as aves do céu, ninhos; mas o Filho do Homem não tem onde reclinar a cabeça."
Mateus 8:19,20

Referências:


José Carlos Macoratti