コマンド
公開日: 2025/06/02
コマンドパターンとは?──操作をオブジェクト化し、記録・再生・取り消しを可能にする設計
はじめに
ユーザーの操作を「取り消し(Undo)」できるようにしたい、あるいは実行内容を記録・再生・キューイングしたい──そんなとき、処理をそのまま記述するだけでは柔軟な制御は難しいものです。
こうしたニーズに応えるのが「コマンドパターン(Command Pattern)」。処理を“オブジェクト”として扱い、実行を遅延・記録・取り消し可能にする構造です。
基本情報・概要
コマンドパターンとは、命令(コマンド)をオブジェクトとしてカプセル化し、呼び出し側と実行側を分離するデザインパターンです。
操作を抽象化し、「あとで実行する」「まとめて実行する」「取り消す」などが実現可能になります。
主な目的:
- 処理内容を再利用・記録・キューとして操作
- 実行側と呼び出し側の疎結合化
- Undo/Redo 機能の実現
比較・分類・特徴の表形式まとめ(任意)
構成要素 | 役割・説明 |
---|---|
Command | 実行される操作のインターフェース(抽象) |
ConcreteCommand | 実際の処理内容を実装(命令の本体) |
Receiver | 実行対象のオブジェクト(処理を持つ) |
Invoker | Commandを実行・保持・取り消す制御側 |
Client | Commandを作ってInvokerに渡すアプリケーションの利用者 |
コマンドは「処理を関数ではなく“オブジェクト”として持つ」構造が本質です。
深掘り解説
✅ JavaScriptによる実装例
// Receiver(処理本体) class Light { on() { console.log("ライトを点けました"); } off() { console.log("ライトを消しました"); } } // Command インターフェース class Command { execute() {} undo() {} } // ConcreteCommand class LightOnCommand extends Command { constructor(light) { super(); this.light = light; } execute() { this.light.on(); } undo() { this.light.off(); } } // Invoker class RemoteControl { setCommand(command) { this.command = command; } pressButton() { this.command.execute(); } pressUndo() { this.command.undo(); } } // 実行 const light = new Light(); const onCommand = new LightOnCommand(light); const remote = new RemoteControl(); remote.setCommand(onCommand); remote.pressButton(); // => ライトを点けました remote.pressUndo(); // => ライトを消しました
- コマンドが処理を「保持」し、呼び出し側(Invoker)と実行側(Receiver)を分離
- Undo処理がシンプルに実現可能
応用・発展的な使い方
- Undo/Redo機能:エディタ、ゲーム、フォーム操作などで活用
- リモート実行の操作記録:コマンドを送信→順次実行する構造
- バッチ処理・キュー制御:コマンドを蓄積して逐次/並列実行
- マクロコマンド:複数のコマンドをまとめて1つにする構造(Commandの中で複数のCommand実行)
「ユーザーの操作そのものをオブジェクト化する」ことで、操作の柔軟な制御と管理が可能になります。
よくある誤解と注意点(任意)
- 「ただ関数を呼べばいいのでは?」:一時保存やUndo/Redo、非同期制御が必要ならCommandが有効
- 責務の分散が難しい:どこまでCommandに任せるか、Receiverに寄せるかは設計次第
- 大量のConcreteCommandクラスが必要になることも:処理の粒度や共通化を意識
- Invokerが肥大化しやすい:状態保持・履歴管理などの切り出しがポイント
コマンドは「何をするかをデータとして扱う」設計の代表格です。
まとめ
コマンドパターンは、操作(処理)を“命令オブジェクト”としてカプセル化し、柔軟な実行制御を可能にする設計パターンです。
ユーザー操作の記録・取り消し・再実行などの高度な要件に対して、機能を整理しながら保守可能な構造を提供します。
「今すぐ実行する」のではなく、「後でどう動かすかを設計する」ことが重要なシステムにおいて、コマンドパターンは非常に効果的なアプローチです。