0
0

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で実装するStateパターン:状態によって振る舞いを動的に切り替える

Posted at

概要

State(ステート)パターンは、
オブジェクトの内部状態によって振る舞い(メソッドの挙動)を動的に切り替えることを目的とした振る舞い系のデザインパターンである。

各状態をクラスとして定義することで、
状態ごとの責務分離と状態遷移の可視化・制御を実現できる


1. なぜStateパターンが必要か?

❌ 条件分岐で状態を管理しようとする設計

if state == "locked":
    ...
elif state == "unlocked":
    ...

→ 条件が増えるたびにメソッドが肥大化し、保守困難になる


✅ 状態ごとに専用のクラスを用意し、振る舞いを分離

context.set_state(LockedState())
context.press_button()  # 状態に応じた処理を実行

状態クラスに応じた処理をカプセル化し、切り替えを直感的に


2. 基本構造

✅ State(共通インターフェース)

class State:
    def handle(self, context):
        raise NotImplementedError

✅ ConcreteStates(具体的な状態)

class LockedState(State):
    def handle(self, context):
        print("🔒 ドアはロックされています。開けられません。")
        context.set_state(UnlockedState())

class UnlockedState(State):
    def handle(self, context):
        print("🔓 ドアが開きました。ロックします。")
        context.set_state(LockedState())

✅ Context(状態管理本体)

class Door:
    def __init__(self):
        self._state = LockedState()

    def set_state(self, state: State):
        self._state = state

    def press_button(self):
        self._state.handle(self)

✅ 使用例

door = Door()
door.press_button()  # 🔒 → 🔓
door.press_button()  # 🔓 → 🔒
door.press_button()  # 🔒 → 🔓

3. Python的応用:動的に戦略を切り替えるオブジェクト設計

class Player:
    def __init__(self):
        self._state = NormalState()

    def change_state(self, state):
        self._state = state

    def move(self):
        self._state.move()

class NormalState:
    def move(self):
        print("通常移動(速度1x)")

class SpeedUpState:
    def move(self):
        print("加速移動(速度2x)")
player = Player()
player.move()
player.change_state(SpeedUpState())
player.move()

振る舞いを状態インスタンスで切り替える柔軟な実装


4. 実務ユースケース

✅ ゲーム内のキャラクター挙動制御(通常 / 無敵 / 麻痺)

状態によって移動・攻撃の挙動を切り替え


✅ フォームウィザードの状態管理(入力 → 確認 → 完了)

状態ごとの画面/バリデーションロジックを分離


✅ ネットワーク接続状態(未接続 / 接続中 / 切断中)

接続処理の流れとUI反映を状態に応じて制御


✅ チケットライフサイクル管理(発行 / 使用中 / 完了)

ステータス遷移に応じて処理内容を変更


5. よくある誤用と対策

❌ Contextが状態ごとの処理を知りすぎてしまう

→ ✅ 処理はState側に委譲し、Contextは状態の保持と切り替えに限定


❌ 状態クラスが過剰に肥大化

→ ✅ 状態ごとの責務を明確かつシンプルに分割


❌ 状態が1つしか存在しない用途に適用

→ ✅ Stateパターンは状態と振る舞いが複数存在し、動的に切り替える必要がある場合に有効


結語

Stateパターンとは、“振る舞いを状態に委ね、コードに動的な表現力を与える構造設計”である。

  • 状態に応じた振る舞いの切り替えを責務分離とカプセル化で明示的に管理
  • 条件分岐の塊を状態クラスとして独立させ、拡張性と保守性を向上
  • Pythonではクラスの柔軟性とシンプルな構造により、状態遷移を明快に実装可能

Pythonicとは、“現在の文脈に応じて振る舞いを変える柔軟さ”を保つこと。
Stateパターンはそのコンテキストの動的変化を、構造で美しく捉える設計技法である。

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?