1. パターンの意図
コマンド(Command)パターン は、
操作(リクエスト)をオブジェクトとしてカプセル化し、呼び出し元と実行処理を分離する デザインパターンです。
解決する問題
- 「操作の履歴」「取り消し(Undo)」「やり直し(Redo)」を柔軟に実装したい
- 呼び出し側(Invoker)と実行側(Receiver)の結合度を下げたい
- リクエストをキューに貯めて順番に実行したい
ポイント
- Command:操作を表す抽象インターフェース
- ConcreteCommand:実際の処理を持つクラス
- Invoker:Command を実行する(呼び出す)側
- Receiver:実際の処理を行う対象
2. UML 図
3. Flutter / Dart 実装例
Command インターフェース
abstract class Command {
void execute();
}
Receiver
class Light {
void turnOn() => print("Light is ON");
void turnOff() => print("Light is OFF");
}
ConcreteCommand
class TurnOnCommand implements Command {
final Light light;
TurnOnCommand(this.light);
@override
void execute() => light.turnOn();
}
class TurnOffCommand implements Command {
final Light light;
TurnOffCommand(this.light);
@override
void execute() => light.turnOff();
}
Invoker
class RemoteControl {
Command? _command;
void setCommand(Command command) {
_command = command;
}
void pressButton() {
_command?.execute();
}
}
利用例
void main() {
var light = Light();
var remote = RemoteControl();
remote.setCommand(TurnOnCommand(light));
remote.pressButton(); // Light is ON
remote.setCommand(TurnOffCommand(light));
remote.pressButton(); // Light is OFF
}
4. Android / Kotlin 実装例
Command
interface Command {
fun execute()
}
Receiver
class Light {
fun turnOn() = println("Light is ON")
fun turnOff() = println("Light is OFF")
}
ConcreteCommand
class TurnOnCommand(private val light: Light) : Command {
override fun execute() = light.turnOn()
}
class TurnOffCommand(private val light: Light) : Command {
override fun execute() = light.turnOff()
}
Invoker
class RemoteControl {
private var command: Command? = null
fun setCommand(command: Command) {
this.command = command
}
fun pressButton() {
command?.execute()
}
}
利用例
fun main() {
val light = Light()
val remote = RemoteControl()
remote.setCommand(TurnOnCommand(light))
remote.pressButton() // Light is ON
remote.setCommand(TurnOffCommand(light))
remote.pressButton() // Light is OFF
}
5. 実務ユースケース
Flutter
- ボタン操作を Command としてカプセル化(Undo/Redo対応)
- 履歴管理(テキスト編集、UIアクション)
- Bloc / Redux のアクション設計にも近い
Android (Kotlin)
- UI ボタン → Command → Receiver(Service/Repository)
- 操作履歴を保存して Undo/Redo 実装
- Job キューや WorkManager によるタスク実行
6. メリット / デメリット
メリット
- 呼び出しと実行を分離 → 疎結合
- Undo/Redo・履歴管理が容易
- 複雑な操作キューを柔軟に扱える
デメリット
- クラス数が増える(CommandごとにConcreteCommandが必要)
- 小さな処理にはオーバーエンジニアリング
まとめ
- Command パターンは「リクエストをオブジェクト化して実行を分離」する仕組み
- Flutter/Android では Undo/Redo、操作履歴、非同期ジョブ実行に便利
- Strategy が「アルゴリズムを差し替え」なら、Command は「操作を記録して実行」