gof-command について
gof-command は、要求をオブジェクトとして表し、呼び出し元と処理を分離する Command パターンを解説するスキルです。実行、任意の取り消し、キューイング、スケジューリング、複合化と、適用判断の指針を扱います。
主な機能
- 01要求をオブジェクトとしてカプセル化
- 02呼び出し元と処理対象を分離
- 03実行と任意の取り消しに対応
- 04コマンドをマクロとして合成
- 05適用判断の指針とアンチパターン
活用シーン
- 01UI 操作と実装を分離
- 02処理をキューイングまたはスケジュール
- 03取り消しと再実行を追加
- 04操作の列を記録して実行
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill gof-commandインストール後、Claude Code で/gof-commandを入力して読み込まれたか確認します。
詳細
1 行での概要
リクエストをオブジェクトとしてカプセル化し、アクションを「誰がトリガーするか」と「何を実行するか」に分離します。これにより、リクエストをパラメーター化、キューイング、記録、取り消し、または合成できるようになります。
このスキルを使う場面
- 呼び出し元(UI ボタン、スケジューラー、キューハンドラー)がアクションをトリガーする必要があるものの、その内容を知るべきではない場合。
- 操作をキューイング、スケジュール、再試行、または記録する必要がある場合。
- 取り消し/やり直し機能が必要な場合。各コマンドが、自身の実行方法と取り消し方法を把握します。
- マクロレコーダーを構築する場合。コマンドのリストを保持し、順に実行するコマンドです。
- 「何を実行するか」と「いつ実際に実行するか」のタイミングを分離する場合。
このスキルを使わない場面
- 直接メソッドを呼び出せば十分で、分離する必要がない場合。
- 「コマンド」が引数もライフサイクルもない単一の関数である場合。それは単なる関数参照です。
- システムに、すでにこの役割を担うジョブキュー/メッセージバスがある場合。
主な内容
Command は次の要素をまとめます。
- レシーバー(アクションの実行対象となるオブジェクト)。
- アクション(呼び出す操作)。
- 引数(アクションに必要なデータ)。
呼び出し元は Command への参照を保持し、コマンド内部で何が行われるかを知らずに execute() を呼び出します。具象コマンドは execute() と、任意で undo() を実装します。
代表的な例は、各ボタンが Command を保持するテレビのリモコンです。リモコンは、ボタンが照明をつけるのか、ガレージのドアを開けるのか、ステレオを起動するのかを知りません。各ボタンは、自身のコマンドに対して execute() を呼び出すだけです。
合成する場合、MacroCommand は Command のリストを保持し、順に実行します。マクロを取り消す場合は、順序を逆にします。
判断の目安
- 取り消し/やり直しが必要なら、Command を出発点にします。
- アクションのスケジューリング、再試行、またはリモート実行が必要なら、Command は転送する単位として自然です。
- 各 Command は小さく、明確な目的を 1 つだけ持つべきです。複数のステップからなる大きなコマンドは、
MacroCommandにまとめます。 - 取り消しを機能させるために、
execute()とundo()が以前の状態を保持する必要がある場合、Command は実行時にその状態を記録する必要があります(メメントスタイル)。
アンチパターン
- グローバル状態を変更し、
undo()を持たないコマンド。パターンの主な価値が失われます。 execute()だけを持ち、ほかに存在理由のないコマンドクラス。関数参照で十分です。- レシーバーに委譲せず、ビジネスロジックを Command の中に置くこと。Command はリクエストであり、実装ではありません。
- 「タイプコードに対する switch を持つ巨大な GodCommand を 1 つだけ作る」こと。これは Command クラスの中に隠れた Simple Factory です。種類ごとにコマンドを分けてください。
関連項目
gof-strategy— どちらも振る舞いをラップしますが、Strategy はアルゴリズムの切り替え、Command はリクエストのキューイング/スケジューリング/取り消しを目的とします。gof-observer— コマンドがイベントによってトリガーされる場合。gof-kotlin-idioms— Kotlin の関数型(() -> Unit)とラムダ式を使えば、最も単純な Command のケースをインターフェースなしで実現できます。
参考資料
- Head First Design Patterns(第 2 版)、第 6 章(「呼び出しのカプセル化:Command パターン」) — プログラム可能な家庭用リモコンを題材にした代表的な解説。
コメント
Markdown 対応