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()