【ITニュース解説】Command Pattern in Rust - absolutely driven by intrinsic motivation...

2025年09月05日に「Dev.to」が公開したITニュース「Command Pattern in Rust - absolutely driven by intrinsic motivation...」について初心者にもわかりやすいように丁寧に解説しています。

作成日: 更新日:

ITニュース概要

Rustでデザインパターンの一種「コマンドパターン」を実装する記事。このパターンは「命令を出す側」と「実行する側」を分離する設計手法だ。これにより、命令側は実行内容を知らなくても様々な命令を統一的に扱え、プログラムの柔軟性が向上する。(111文字)

ITニュース解説

プログラミングの世界には、多くの開発者が繰り返し直面する特定の問題を解決するための、確立された設計手法が存在する。これらは「デザインパターン」と呼ばれ、いわば設計における定石や型のようなものである。デザインパターンを学ぶことで、コードの再利用性や保守性を高め、より柔軟で拡張しやすいシステムを構築できるようになる。今回は、その中でも特に有名な「コマンドパターン」について、プログラミング言語Rustでの実装例を通じて解説する。

コマンドパターンとは、何かを実行する「要求」そのものをオブジェクトとしてカプセル化(ひとまとめに)するデザインパターンである。これにより、要求を出す側と、その要求を実際に処理する側を分離することができる。このパターンの本質を理解するために、レストランの運営を想像してみると良い。客からの注文(要求)をウェイターが受け、シェフに伝えて料理が作られる。この一連の流れにコマンドパターンを当てはめてみよう。

このパターンには、主に4つの登場人物がいる。一つ目は、要求を実行するように指示を出す「Invoker(起動者)」。レストランの例では「ウェイター」にあたる。二つ目は、実行されるべき操作のすべてをカプセル化した「Command(コマンド)」。これは「注文票」に相当する。三つ目は、そのコマンドの具体的な内容を実装した「Concrete Command(具体的なコマンド)」で、「パスタを作る」や「ステーキを焼く」といった個別の注文票がこれにあたる。そして四つ目が、実際に処理を行う「Receiver(受信者)」。レストランでは「シェフ」がこの役割を担う。

コマンドパテーンの最大の利点は、ウェイター(Invoker)がシェフ(Receiver)の具体的な仕事内容、つまり「パスタをどうやって作るか」を知る必要がない点にある。ウェイターの仕事は、注文票(Command)をシェフに渡すことだけだ。これにより、ウェイターとシェフの間の依存関係が薄まる。これを専門用語で「疎結合」と呼ぶ。もし新しいメニューが増えても、新しい注文票とそれを作れるシェフを用意すればよく、ウェイターの仕事のやり方を変える必要はない。このように、システムの変更に強い構造を作れるのがコマンドパテーンの強みである。

それでは、この仕組みをRustのコードでどのように実現するかを見ていこう。まず、あらゆるコマンドが共通して持つべき振る舞いを定義する。Rustでは、このような共通のインターフェースを「トレイト」という機能で表現する。記事のコードではtrait Commandがそれに該当し、すべてのコマンドはexecuteというメソッド(関数)を持つ、というルールを定めている。

次に、実際の作業者であるシェフ(Receiver)をstruct Chefとして定義する。このシェフはprepare_foodという、料理を準備する具体的な能力を持っている。これが、最終的に実行される処理の本体となる。

続いて、具体的なコマンド(Concrete Command)であるFoodCommandを定義する。このFoodCommandは、どのシェフに作業を依頼するかを情報として内部に保持している(chef: Chefの部分)。そして、先ほど定義したCommandトレイトをFoodCommandに実装する。そのexecuteメソッドの中身は、保持しているシェフに対してprepare_foodメソッドを呼び出す、という処理になる。これで「料理を作れ」という命令が完成した。

最後に、命令を出すウェイター(Invoker)をstruct Waiterとして定義する。ここが最も重要な部分で、ウェイターはcommand: Box<dyn Command>という形でコマンドを保持する。これは「Commandトレイトを実装している何らかのオブジェクト」を保持できる、という意味だ。ウェイターは、渡されたコマンドがFoodCommandなのか、あるいは将来作られるかもしれないDrinkCommandなのか、その具体的な種類を一切気にする必要がない。ただCommandというルールに従っていることだけを知っていれば良い。このBox<dyn Command>は「トレイトオブジェクト」と呼ばれ、具体的な型を隠蔽し、共通の振る舞い(ここではexecuteメソッド)だけに着目してオブジェクトを扱うことを可能にする、Rustの強力な機能である。ウェイターのpass_command_to_chefメソッドは、自身が保持しているコマンドのexecuteメソッドを呼び出すだけだ。これにより、ウェイターはコマンドの具体的な中身を知ることなく、ただ実行の指示を出すという役割に専念できる。

main関数では、これら登場人物をすべて用意し、シェフと料理コマンドを作成し、それをウェイターに渡して実行させる、という一連の流れが示されている。この構造により、例えば新しい「デザートを作る」というコマンドDessertCommandを追加したくなった場合でも、Waiterのコードを一切変更することなく、システムを拡張できる。

コマンドパターンは、要求をオブジェクトとして扱えるようにするため、要求をキューに溜めておいて後で実行したり、実行したコマンドの履歴を保存して「元に戻す(Undo)」や「やり直す(Redo)」機能を実装したりする際にも非常に役立つ。このように、コマンドパターンはプログラムの各要素の役割を明確に分離し、柔軟性と拡張性の高いシステム設計を実現するための強力なツールである。Rustでは、クラスベースのオブジェクト指向言語とは異なり、トレイトと構造体を組み合わせることで、このパターンを効果的に実装することができるのだ。

【ITニュース解説】Command Pattern in Rust - absolutely driven by intrinsic motivation... | いっしー@Webエンジニア