0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで実装するCommandパターン:操作のリクエストをオブジェクト化して柔軟に実行

Posted at

概要

Command(コマンド)パターンは、
「操作(命令)」をオブジェクトとして定義し、実行要求・取り消し・履歴管理・非同期処理などを柔軟に扱う設計パターンである。

操作の発行者(Invoker)と実行者(Receiver)を分離し、実行タイミングの制御やUndo処理の実装に適している


1. なぜCommandが必要か?

❌ 操作の実行ロジックをその場で直接書くと、柔軟性に欠ける

button.on_click = lambda: editor.copy()

操作の再実行・取り消し・記録が困難


✅ 操作自体をオブジェクト化し、どこからでも呼び出せるようにする

copy_command = CopyCommand(editor)
button.set_command(copy_command)

Commandにより、操作の発行と実行を分離・構造化できる


2. 基本構造

✅ Commandインターフェース

class Command:
    def execute(self):
        raise NotImplementedError

✅ Receiver(実際の処理を行う対象)

class Editor:
    def copy(self):
        print("コピー実行")

    def paste(self):
        print("ペースト実行")

✅ Concrete Command

class CopyCommand(Command):
    def __init__(self, editor: Editor):
        self.editor = editor

    def execute(self):
        self.editor.copy()

class PasteCommand(Command):
    def __init__(self, editor: Editor):
        self.editor = editor

    def execute(self):
        self.editor.paste()

✅ Invoker(実行を依頼する側)

class Button:
    def __init__(self):
        self._command = None

    def set_command(self, command: Command):
        self._command = command

    def click(self):
        if self._command:
            self._command.execute()

✅ 使用例

editor = Editor()
copy = CopyCommand(editor)
paste = PasteCommand(editor)

copy_button = Button()
paste_button = Button()

copy_button.set_command(copy)
paste_button.set_command(paste)

copy_button.click()  # コピー実行
paste_button.click()  # ペースト実行

3. Python的応用:関数やクロージャでもCommandを表現可能

class FunctionCommand(Command):
    def __init__(self, func):
        self._func = func

    def execute(self):
        self._func()

cmd = FunctionCommand(lambda: print("関数ベースで実行"))
cmd.execute()

Pythonでは関数もファーストクラスオブジェクトなのでCommandと相性が良い


4. 実務ユースケース

✅ GUIアプリケーションにおけるボタン・メニュー・ショートカット操作

ユーザー操作をCommandとして統一的に扱える


✅ Undo / Redo 機能

→ コマンドを履歴として保存し、undo()で逆操作を実行


✅ ジョブスケジューラ・非同期タスクキュー

→ 操作をCommandとしてあとから実行・再実行・遅延実行できる


✅ ロボット制御・ゲーム内アクションスクリプト

→ 各アクションをCommand化してシナリオ制御を柔軟に


5. よくある誤用と対策

❌ CommandがReceiverに強く依存しすぎる

→ ✅ 依存関係はインターフェース経由で渡すように設計する


❌ Commandの実装が増えすぎてクラス数が肥大

→ ✅ 関数ベースの簡易Commandや、Commandファクトリで整理する


❌ Undo/Redo用の逆操作をCommandに書きすぎる

→ ✅ Commandは“実行”と“取り消し”を分離して明示的に設計する

class UndoableCommand(Command):
    def undo(self):
        raise NotImplementedError

結語

Commandパターンとは、“操作そのものをデータとして扱い、実行の柔軟性を引き出す設計”である。

  • 操作をオブジェクト化することで、履歴・再実行・非同期処理が可能に
  • 実行と依頼の分離により、疎結合で再利用可能な構造を実現
  • Pythonでは関数・クラス両方で、極めて軽量かつ柔軟に実装可能

Pythonicとは、“動作を抽象化して渡すこと”。
Commandパターンはその動的操作性を、設計の表現力に変える技法である。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?