概要
**コマンドパターン(Command Pattern)**は、操作(アクション)をオブジェクトとして抽象化し、
実行、取り消し、再実行といった履歴管理や非同期処理、バッチ化などを容易にする設計パターンである。
本稿では、Pythonにおけるコマンドパターンの実装と応用に加えて、
Undo機能の構築やマクロ処理との連携など、実務に直結する設計戦略を紹介する。
1. なぜCommandが必要か?
❌ 呼び出し側が操作の中身を知っている
editor.save()
editor.undo()
editor.print_document()
→ 呼び出し側が editor
の振る舞いをすべて知っており、疎結合性が崩壊
✅ 操作そのものを「コマンド」として抽象化
command = SaveCommand(editor)
invoker.execute(command)
→ 実行対象(editor)や操作の詳細から 呼び出し元を切り離せる
2. 基本構造
✅ コマンドインタフェース
class Command:
def execute(self): ...
def undo(self): ...
✅ 具体的なコマンド
class AddTextCommand(Command):
def __init__(self, editor, text):
self.editor = editor
self.text = text
def execute(self):
self.editor.add(self.text)
def undo(self):
self.editor.remove_last()
✅ 呼び出し元(Invoker)
class CommandInvoker:
def __init__(self):
self.history = []
def execute(self, command):
command.execute()
self.history.append(command)
def undo(self):
if self.history:
self.history.pop().undo()
3. 使用例:簡易エディタ
class TextEditor:
def __init__(self):
self.content = []
def add(self, text):
self.content.append(text)
def remove_last(self):
if self.content:
self.content.pop()
def show(self):
print("".join(self.content))
editor = TextEditor()
invoker = CommandInvoker()
invoker.execute(AddTextCommand(editor, "Hello "))
invoker.execute(AddTextCommand(editor, "World!"))
editor.show() # Hello World!
invoker.undo()
editor.show() # Hello
4. 応用パターン:バッチ化・マクロ処理
class MacroCommand(Command):
def __init__(self):
self.commands = []
def add(self, command):
self.commands.append(command)
def execute(self):
for c in self.commands:
c.execute()
def undo(self):
for c in reversed(self.commands):
c.undo()
→ 一連の操作を 一つのコマンドとして扱う
→ マクロ録音・再生機能に応用可能
5. 非同期コマンドの設計(asyncio対応)
class AsyncCommand:
async def execute(self): ...
async def undo(self): ...
→ タスクキュー、ジョブ実行制御、スケジューラとの親和性が高い
6. 実務ユースケース
- テキストエディタのUndo/Redo機構
- GUIアプリでのボタン動作の動的バインディング
- バッチ実行処理のキューイングとリトライ
- ゲーム開発におけるユーザー操作の記録・再生
7. よくある誤用と対策
❌ コマンドが実行対象の内部を操作しすぎる
→ ✅ コマンドは 1つの動作単位に徹するべき。副作用や状態変更の責務を分離
❌ Undo実装を省略して履歴が中途半端に
→ ✅ undo()
を最初から設計に組み込み、再現可能性・整合性を担保
❌ コマンド生成の責務が呼び出し元に集中
→ ✅ CommandFactory
や DI で生成を抽象化
結語
コマンドパターンは、アクションをオブジェクト化することで、
操作の追跡・記録・巻き戻し・再実行を可能にする構造である。
- 単一責任で定義されたコマンドにより、操作の可搬性と再利用性が高まる
- 呼び出し元との疎結合を維持しながら、振る舞いを動的に切り替える設計が可能
- Undo機能、マクロ処理、非同期ジョブといった高度なアプリケーション要件に自然に適応
Pythonicとは、“操作を動作としてではなくデータとして設計する”ことであり、
コマンドパターンはその構造的思考を最も象徴的に表す手段である。