面白いことに、この質問は、私が取り組んでいたコミュニケーションライブラリについて、エンジニアの1人とまったく同じ会話を思い出したことです。
コマンドの代わりに、Requestクラスがあり、その後RequestHandlerがありました。デザインは、あなたが説明しているものと非常に似ていました。あなたが持っている混乱の一部は、英語の「コマンド」という言葉を見て、即座に「動詞、行動...など」と考えることだと思います。
しかし、この設計では、コマンド(またはリクエスト)を文字と考えてください。または、郵便サービスとは何かを知らない人のために、電子メールを考えてください。それは単にコンテンツであり、そのコンテンツがどのように行動されるべきかから切り離されています。
なぜこれをするのですか?Command Patternのほとんどの単純なケースでは、理由はなく、このクラスに直接作業を実行させることができます。ただし、アクション/コマンド/リクエストがある程度の距離を移動する必要がある場合、設計のようにデカップリングを行うことは理にかなっています。たとえば、接続、ソケット、パイプ、またはドメインとインフラストラクチャ間。または、アーキテクチャ内でコマンドを永続化する必要があるかもしれません(たとえば、コマンドハンドラーは一度に1つのコマンドを実行できます。一部のシステムイベントにより、200コマンドが到着し、最初の40プロセスがシャットダウンした後)。その場合、単純なメッセージのみのクラスを使用すると、メッセージ部分だけをJSON / XML / binary / whateverにシリアル化し、コマンドハンドラーで処理できるようになるまでパイプラインに渡すことが非常に簡単になります。
CommandHandlerからCommandを切り離すことのもう1つの利点は、並列継承階層のオプションが用意されたことです。たとえば、すべてのコマンドは、シリアル化をサポートする基本コマンドクラスから派生できます。また、20個のコマンドハンドラのうち4個が非常に類似していて、来たハンドラの基本クラスから派生できる可能性があります。1つのクラスでデータとコマンドを処理する場合、このタイプの関係はすぐに制御不能になります。
分離の別の例は、コマンドが非常に小さな入力(2つの整数と文字列)を必要とするが、その処理ロジックがデータを中間メンバー変数に格納するのに十分複雑な場合です。50個のコマンドをキューに入れる場合、その中間ストレージすべてにメモリを割り当てたくないため、CommandHandlerからCommandを分離します。これで、50個の軽量データ構造をキューに入れ、より複雑なデータストレージが、コマンドを処理しているCommandHandlerによって1回のみ(または、N個のハンドラーがある場合はN回)割り当てられます。