Engraçado, essa pergunta me lembrou exatamente a mesma conversa que tive com um de nossos engenheiros sobre a biblioteca de comunicações em que estava trabalhando.
Em vez de comandos, eu tinha classes Request e, em seguida, tinha RequestHandlers. O design era muito parecido com o que você está descrevendo. Eu acho que parte da confusão que você tem é que você vê a palavra em inglês "comando" e pensa instantaneamente em "verbo, ação ... etc".
Mas neste design, pense em Command (ou Request) como uma carta. Ou para aqueles que não sabem o que é um serviço postal, pense no e-mail. É simplesmente conteúdo, dissociado de como esse conteúdo deve ser usado.
Por que você faria isso? Na maioria dos casos simples, do Padrão de Comando não há razão e você pode fazer com que essa classe execute o trabalho diretamente. No entanto, fazer a dissociação como no seu design faz sentido se sua ação / comando / solicitação precisar percorrer alguma distância. Por exemplo, entre, soquetes ou tubulações, ou entre domínio e infraestrutura. Ou talvez na sua arquitetura seus comandos precisem ser persistentes (por exemplo, o manipulador de comandos pode executar 1 comando por vez, devido a alguns eventos do sistema, 200 comandos chegam e após os primeiros 40 processos serem desligados). Nesse caso, tendo uma classe simples de mensagem, torna-se muito simples serializar apenas a parte da mensagem em JSON / XML / binário / qualquer que seja e transmiti-la pelo pipeline até que seu manipulador de comandos esteja pronto para processá-la.
Outra vantagem da dissociação do Command do CommandHandler é que agora você tem a opção de hierarquia de herança paralela. Por exemplo, todos os seus comandos podem derivar de uma classe de comando base que suporta serialização. E talvez você tenha 4 dos 20 manipuladores de comando que têm muita semelhança, agora você pode derivar aqueles da classe base do manipulador fornecido. Se você tivesse manipulação de dados e comandos em uma classe, esse tipo de relacionamento rapidamente sairia do controle.
Outro exemplo para a dissociação seria se o seu comando exigisse muito pouca entrada (por exemplo, 2 números inteiros e uma string), mas sua lógica de manipulação fosse complexa o suficiente para que você desejasse armazenar dados nas variáveis de membro intermediárias. Se você enfileirar 50 comandos, não deseja alocar memória para todo esse armazenamento intermediário, para separar Command e CommandHandler. Agora você enfileira 50 estruturas de dados leves e o armazenamento de dados mais complexo é alocado apenas uma vez (ou N vezes se você tiver N manipuladores) pelo CommandHandler que está processando os comandos.