概要
**状態パターン(State Pattern)**は、
オブジェクトの内部状態に応じて、その振る舞い(メソッドの実装)を動的に切り替える設計手法。
状態をクラスとして独立させることで、条件分岐の削減、状態遷移の明示、振る舞いの分離が可能となり、
複雑な状態管理を洗練された構造で実現できる。
本稿では、Pythonにおける状態パターンの実装と実務活用例を解説する。
1. なぜStateパターンが必要か?
❌ 状態に応じた if-else が膨張する構造
if self.state == "draft":
self.save_as_draft()
elif self.state == "submitted":
self.submit_to_approval()
elif self.state == "approved":
self.lock()
→ 状態が増えるたびに分岐が複雑化、保守困難に
✅ 状態ごとの振る舞いをクラスに分離
class DraftState:
def handle(self, context): ...
class ApprovedState:
def handle(self, context): ...
→ 状態をオブジェクトとして設計することで、処理がスケーラブルに
2. 基本構造
✅ 状態インタフェース
class State:
def submit(self, context): raise NotImplementedError
def approve(self, context): raise NotImplementedError
✅ 具体的状態クラス
class Draft(State):
def submit(self, context):
print("Submitted")
context.set_state(Submitted())
def approve(self, context):
print("Cannot approve draft")
class Submitted(State):
def submit(self, context):
print("Already submitted")
def approve(self, context):
print("Approved")
context.set_state(Approved())
class Approved(State):
def submit(self, context):
print("Already approved")
def approve(self, context):
print("Already approved")
✅ コンテキストクラス
class Document:
def __init__(self):
self.state = Draft()
def set_state(self, state):
self.state = state
def submit(self):
self.state.submit(self)
def approve(self):
self.state.approve(self)
✅ 実行例
doc = Document()
doc.submit() # → Submitted
doc.approve() # → Approved
doc.approve() # → Already approved
3. 状態パターンのメリット
- 状態ごとの処理が明確に分離されるため、可読性と拡張性が高い
- 状態遷移のルールをオブジェクトレベルで管理できる
- if-else地獄を排除し、振る舞いを構造としてモデル化できる
4. 実務的ユースケース
✅ ワークフロー管理
- 「作成 → 提出 → 承認 → 完了」といった複雑な状態遷移を制御
- 各状態における許可アクションをクラス内で定義し、フローの正当性を担保
✅ UIコンポーネントの状態制御
- ボタン:enabled / hovered / clicked / disabled
- 状態クラスを切り替えることで、描画や振る舞いを一貫管理
✅ ゲーム開発:プレイヤーのステート管理
- 例:Idle, Running, Attacking, Dying
- 各状態が
enter()
,exit()
,update()
を持ち、状態マシンの構築が容易
5. Python的に書きやすくする工夫
✅ EnumとStateクラスの併用
from enum import Enum
class Status(Enum):
DRAFT = "draft"
SUBMITTED = "submitted"
APPROVED = "approved"
→ 状態の識別子をEnumで定義し、Stateインスタンスとマッピング
✅ 状態テーブルで動的切替(簡易型)
class StateMachine:
def __init__(self):
self.state = "draft"
def transition(self, event):
rules = {
("draft", "submit"): "submitted",
("submitted", "approve"): "approved"
}
self.state = rules.get((self.state, event), self.state)
→ 小規模なら状態テーブルで管理するパターンも選択肢に
6. よくある誤用と対策
❌ 状態を文字列や数値で持ち続ける
→ ✅ State
クラスとして定義し、振る舞いと状態を結合させる
❌ 状態間の遷移ロジックをコンテキスト側に書く
→ ✅ 状態クラスが自身の遷移先を決定することで、流れが一元化される
結語
状態パターンは、「条件分岐による振る舞いの切替」を「構造による振る舞いの委譲」に変換する設計手法である。
- 状態の数が増えるほど、構造化の恩恵が大きくなる
- 分岐の除去、可視性の向上、状態遷移の明示という、実務的な設計課題に直結
- Pythonのクラスベース設計との親和性も高く、OOPの理解深化にも繋がる
Pythonicとは、“条件を消し、構造で語る”ことであり、
状態パターンはその哲学を実現するための洗練された形式である。