Command パターン

**Command パターン**（）は、オブジェクト指向プログラミングにおいて、処理の要求と実行を分離するためのデザインパターンである。処理内容と必要な情報を Command オブジェクトとしてカプセル化することで、処理の遅延実行やキュー管理、操作履歴の記録および取り消し（undo）などを可能にし、要求側と処理側の結合を弱めることができる。

## 定義

Commandパターンでは何かリクエストを実行する際、単純に処理を実行するのではなく、次のステップを踏む。

# 処理をメソッドとして内包する`'''Command'''`**クラス**の定義
# `'''Command'''`**オブジェクト**の生成
# `Command.'''execute'''()`メソッドのコールによるリクエスト実行

すなわちリクエストを「手順書」の定義・生成とその「実行」に段階分けするパターンをとる。

Commandが内包する処理の記述は開発者に一任されている。全ての処理をCommand内に記述するパターン、あるいは`command`インスタンス生成時に実行者（`Receiver`クラスのインスタンス`receiver`、受信者もしくは観測者とも）を受け取り`command.execute()`時に`receiver.action()`コールのみをおこなう、すなわち実行を`Receiver`に委譲して`Command`は繋ぎに徹するパターンもある。なお、Receiverは特にCommandパターンの要件というわけではない。

`Command`は`Action`、`Transaction`あるいは`Task`とも呼ばれる。

## 利点
このパターンがもつ利点の1つは**リクエスト依頼処理と実装処理の分離**（疎結合）である。

例えばボタンのクリックでリクエストを実行できるUIフレームワークを開発するとする。ボタンのクリック機能とリクエストの実行はフレームワークの責務だが、リクエストの実行によって具体的に何が起こるかはアプリケーションの責務である。すなわちUIフレームワーク側はクリックに応じてリクエストを発行するが、リクエストに対してどのような処理がおこなわれるのか、そもそもリクエストの受け手が誰なのかについては関知しない。ここでボタンの生成時に`Command`を受け入れるとする。UIフレームワーク側は`Command`がどんな処理を内包しているかは（カプセル化されているので）わからないが、`execute()`メソッドを実行すればリクエストが実行されることは知っている。このインターフェイス（interface）を介した契約により、クリック時に`command.execute()`するだけでクリックに応答したリクエストを実行できる。このようにCommandパターンはCommandの実行と実装を疎結合にできる。言い換えれば、Commandパターンは`Command`オブジェクトのDIによる処理と実行の分離（関心の分離）である。これは手続き型プログラミングにおけるコールバック（callback）に相当する。

このパターンがもつもう1つの利点はCommandが**独立したオブジェクト**である点である。未実行の`Command`オブジェクトを配列にいれればキューイングが可能であり、それに応じた非同期処理・スケジューリングが可能になり、実行済みの`Command`をキューイングすれば履歴保存とロギング・アンドゥなどが可能になる。

## 利用例

例としてプリンターによる印刷を考える。

手続き的に実装する場合、印刷設定を引数にとり印刷を実行する`SendJobToPrinter` 関数を叩けばよい。

Commandパターンで実装する場合、`.Execute()` 内に印刷手続きを含む`PrintJob` Commandを用意する。ユーザーは印刷時に`PrintJob` オブジェクトを作成し、印刷するドキュメント・印刷部数などのパラメータをCommandへセット、最後にプリンターへの`PrintJob` 送信メソッドを呼び出す。プリンター側はCommandをキューイングし準備が出来次第`printJob.Execute()`を実行する。

印刷にCommandパターンを利用する利点は以下である。

* コマンド情報の保持: Job名や機能を呼び出したユーザーの情報を保持、参照
*印刷Job全体の情報提供: キューイングに利用した予測時間の提供

## 活用例

Command オブジェクトは下記のような機能を実現するのに便利である。

; 複数回の
: プログラム内の全てのユーザーの操作がコマンドオブジェクトとして実装されれば、プログラムは最近実行されたコマンドのスタックを保持することができるようになる。ユーザーがコマンドをアンドゥしたい場合、プログラムは最後に実行されたコマンドオブジェクトを単純にポップし、そのコマンドオブジェクトの `undo()` メソッドを実行する。さらにアンドゥスタックを別途用意することで、アンドゥされたコマンドを再実行するリドゥ機能を実現することもできる。一般的なドキュメント編集用アプリケーションでは、ドキュメントに対する編集操作に関して、「元に戻す」「やり直し」といったメニューコマンドによってこれらの機能が提供されている。
; トランザクション的振る舞い
: アンドゥの操作が途中で失敗し、前の状態に**巻き戻す**こと（ロールバック）を要求されたときに不可欠である。インストーラやデータベースはこの機能を必要とする。コマンドオブジェクトは2相コミットの実現にも使用できる。
; プログレスバー
: プログラムが一連のコマンドを順番に実行する場合を考える。各コマンドオブジェクトが `getEstimatedDuration()` を持っていれば、プログラムは全体の処理時間を簡単に予測することができる。全てのタスクの完了がどの程度近いのかを意味のある形で示すプログレスバーを表示できる。
; ウィザード
: ウィザードはあるアクションの設定のためにいくつかのページを表示し、最後のページで**完了**ボタンを押すまでアクションは実行されないことが多い。こうした場合、ユーザーインターフェイスのコードとアプリケーションのコードを分離するための自然な方法として、コマンドオブジェクトを用いたウィザードを作成することがある。コマンドオブジェクトはウィザードが最初に表示される際に作成される。ウィザードの各ページはコマンドオブジェクト内に GUI で行われた変更を保存する。*完了*は、`execute()` を呼び出すだけである。このようにしてコマンドオブジェクトの元になるクラスには、一切ユーザーインターフェイスコードを含まないようにすることができる。
; GUI のボタンとメニューの項目
: JavaにおけるアプリケーションフレームワークのひとつSwingでは、インターフェイスを実装する任意のクラスのインスタンスがコマンドオブジェクトである。目的のコマンドを実行する能力に加え、`Action` は関連するアイコンやキーボードショートカット、ツールチップのテキストなどを持つことができる。ツールバーのボタンやメニューのコンポーネントは `Action` オブジェクトのみを使って完全に初期化することができる。DelphiのVisual Component Library (VCL) では基底クラス`Vcl.ActnList.TAction`が用意されている。WPFには`System.Windows.Input.ICommand`インターフェイスが用意されているが、WPFはさらにMVVMパターンを活用した強力なバインディングフレームワークも備えており、XAML上でGUI要素にコマンドを関連付けることもできる。
; スレッドプール
: 典型的な、汎用のスレッドプールクラスは公開された `addTask()` メソッドを持ち、作業項目を内部の完了待ちタスクのキューに追加する。スレッドプールクラスは、キューからコマンドを実行するスレッドのプールを管理する。キュー内の各要素はコマンドオブジェクトである。こうしたコマンドオブジェクトは典型的に `java.lang.Runnable` などの共通のインターフェイスを実装しており、スレッドプールクラス自体に特定のタスクがどのように用いられるかについて一切の情報がなくともコマンドを実行することができる。
; マクロの記録
: あらゆるユーザー操作がコマンドオブジェクトとして表現されていれば、コマンドオブジェクトのリストとして保持するだけで操作の流れを記録できる。その後、コマンドオブジェクトを同じ順序で実行することで、同じ操作を"再生"することができる。プログラムがスクリプトのエンジンを内蔵している場合、各コマンドオブジェクトに `toScript()` メソッドを実装させ、ユーザーの操作をスクリプトとして保存することができる。
; ネットワーク
: コマンドオブジェクトそのものをネットワーク上に送出し、他のマシンに実行させることができる。たとえば、コンピュータゲームのプレイヤーの操作などである。
; 並列処理
: コマンドが共有されたリソースにタスクとして書き込まれ、多数のスレッドで並列に実行される（おそらくはリモートのマシンで）。この方式はマスター/ワーカーパターンと呼ばれていることも多い。
; 移動可能なコード
: とCodebasesを経由してコードをある場所から別の場所にストリーム化・複合化できる Java などの言語を用いると、コマンドは遠隔地に搬送されるという新たな振る舞いをすることができる（EJBコマンド、マスター/ワーカー）。

## 脚注

## 参考文献

* John Gamma, et al. (1994). Design Patterns: Elements of Reusable Object-Oriented Software. **pp.263-273**. Addison-Wesley Professional.
** 原典。いわゆるGoF本

## 関連項目

* クロージャ
* Model View Controller
* 関数オブジェクト
* デザインパターン