KnowHow

技術的なメモを中心にまとめます。
検索にて調べることができます。

Python基礎 オブジェクト指向11(State) 振る舞いに関するデザインパターン

登録日 :2025/10/04 15:37
カテゴリ :Python基礎

State

複数の状態を個別のクラスとして定義し、状態が変化した時に振る舞いを切り替えられるようにするパターン
- 親クラスで各状態が持つべき共通のAPI定義する
- 子クラスで具体的な状態の振る舞いを実装する

構成要素

State

  • インターフェースまたは抽象クラス
  • それぞれの状態に共通のAPIを定義

ConcreteState

  • Stateを継承(実装)する子クラス
  • Stateで定義された共通APIを満たすように各状態ごとの振る舞いを実装する

Context

  • State型のオブジェクトを内部に保持
  • 具体的な処理はStateオブジェクトに移譲する

オブジェクト指向的要素

「継承」「ポリモーフィズム」「委譲」を利用したパターン

  • StateとConcreteStateは継承(実装)関係
  • Stateクラスで共通のAPIを定義し、クライアントはその共通APIを利用することで、具体的な状態クラスの切り替えが可能になる
  • ContextクラスはStateオブジェクトに処理を委譲する

メリット・デメリット

メリット

  • 特定の状態における実装の詳細を別クラスに分離できる
  • 状態に固有の処理を選択するための条件文がなくなる
  • 状態の追加が容易になる

デメリット

  • 状態の種類が少ない場合や状態が滅多に変更されない場合、過剰な設計となる可能性がある

使い所

現在の状態に応じて異なる振る舞いをするオブジェクトがあり、その状態数が多い場合
(Contextに現在の状態をセットすることで振る舞いが切り替わる)

状態の内容が頻繁に変更される場合

状態に固有の処理を実行させるために多くの条件分岐がある場合
(条件分岐を共通なAPIを持った個別のConcreteStateクラスに切り出している)

サンプルコード

ライトのスイッチを切り替える例

from __future__ import annotations
from abc import ABCMeta, abstractmethod


class LightState(metaclass=ABCMeta):
    """State"""
    @abstractmethod
    def switch(self) -> LightState:
        pass


class OffState(LightState):
    """ConcreteState"""
    def switch(self) -> LightState:
        print("ライトを点灯します")
        return OnState()


class OnState(LightState):
    """ConcreteState"""
    def switch(self) -> LightState:
        print("ライトを消灯します")
        return OffState()


class LightSwitch(object):
    """Context"""
    def __init__(self):
        self.__state = OffState()

    def switch(self):
        self.__state = self.__state.switch()


if __name__ == '__main__':
    light_switch = LightSwitch()
    light_switch.switch()
    light_switch.switch()
    light_switch.switch()