概要
Command(コマンド)パターンは、
処理内容(操作)をオブジェクトとして抽象化・独立させることで、呼び出しと実行の分離・Undo/Redoの実装・操作の履歴管理を可能にするデザインパターンである。
この構造により、GUIボタン、キーボードショートカット、メニュー操作などの振る舞いを柔軟に管理可能となる。
1. なぜCommandが必要か?
❌ 操作とUIイベントが直結している設計
def on_button_click():
editor.clear()
→ UIがロジックに強く依存しており、再利用・拡張・テストが困難
✅ 操作をオブジェクトとして切り出し、UIはその実行を委ねる
clear_command = ClearCommand(editor)
clear_command.execute()
→ 操作はCommandオブジェクトとして独立し、複数のトリガーから再利用可能に
2. 基本構造
✅ Commandインターフェース
class Command:
def execute(self):
raise NotImplementedError
def undo(self):
raise NotImplementedError
✅ Receiver(実際に処理される対象)
class Editor:
def __init__(self):
self.content = ""
def write(self, text):
self.content += text
def clear(self):
self.content = ""
def show(self):
print(f"[Editor] {self.content}")
✅ ConcreteCommand(具体的なコマンド)
class ClearCommand(Command):
def __init__(self, editor):
self.editor = editor
self._backup = ""
def execute(self):
self._backup = self.editor.content
self.editor.clear()
def undo(self):
self.editor.content = self._backup
✅ Invoker(コマンドを管理・実行する役)
class CommandInvoker:
def __init__(self):
self._history = []
def run(self, command: Command):
command.execute()
self._history.append(command)
def undo(self):
if self._history:
command = self._history.pop()
command.undo()
✅ 使用例
editor = Editor()
editor.write("Hello, World!")
editor.show()
invoker = CommandInvoker()
clear = ClearCommand(editor)
invoker.run(clear)
editor.show()
invoker.undo()
editor.show()
出力:
[Editor] Hello, World!
[Editor]
[Editor] Hello, World!
3. Python的応用:Lambdaベースの簡易コマンド
class LambdaCommand(Command):
def __init__(self, execute_fn, undo_fn):
self.execute_fn = execute_fn
self.undo_fn = undo_fn
def execute(self):
self.execute_fn()
def undo(self):
self.undo_fn()
→ 小規模な一時的コマンドも柔軟に定義可能
4. 実務ユースケース
✅ GUI操作(ボタン/メニュー/ショートカット)に対する処理の抽象化
→ 同一コマンドを複数UIイベントから呼び出せる
✅ Undo/Redo 機能の実装
→ 各操作を履歴として蓄積し、逆操作を実行
✅ マクロ記録・再生機能
→ コマンドの列を記録・シリアライズ・再実行可能に
✅ リモート実行(キューに蓄積→バッチ実行)
→ 操作内容をオブジェクトとして安全に転送・保存
5. よくある誤用と対策
❌ Commandオブジェクトが複雑な状態を持ちすぎる
→ ✅ 状態は最小限に、処理の委譲先はReceiverに限定する
❌ 実行とUndoが非対称で整合性が取れない
→ ✅ Undo可能な処理のみをCommand化するか、明示的に不可とする
❌ Invokerが複雑なロジックを持つ
→ ✅ Invokerはコマンドの管理と呼び出しだけに集中させる
結語
Commandパターンとは、“操作そのものをオブジェクトとして表現し、自由に扱えるようにする設計手法”である。
- 操作のカプセル化により、UIとロジックの疎結合化と再利用性の向上を実現
- Undo/Redo、バッチ処理、リモートコマンドなど、構造化された操作の応用が可能に
- Pythonではファーストクラスオブジェクトとしての関数やラムダ式により、軽量かつ柔軟にCommand設計が可能
Pythonicとは、“ふるまいもまたデータである”という原則に基づいて構造を抽象化すること。
Commandパターンはその設計思想を、操作としてのコードに昇華させる技法である。