概要
**オブザーバーパターン(Observer Pattern)**は、
あるオブジェクト(Subject)の状態変化に応じて、
複数の依存オブジェクト(Observer)へ通知を送る仕組みを提供する設計パターンである。
この構造はGUIイベント、ログ監視、リアルタイム通知、Pub/Subモデルのようなリアクティブシステムの中核を成す。
本稿では、Pythonでオブザーバーパターンを簡潔かつ強靭に構築する実装例を通じて、
関心の分離とリアクティブ設計の本質を解説する。
1. なぜObserverが必要か?
❌ 状態変化を監視するコードが至る所に散在
def update_ui(data):
if data.changed:
refresh_ui()
def log_change(data):
if data.changed:
write_log()
→ 状態の変更と通知のロジックが分離されておらず、再利用や拡張が困難
✅ オブザーバーパターンで通知をイベント化
subject = Subject()
subject.attach(LoggerObserver())
subject.attach(UiObserver())
subject.set_state("UPDATED")
→ 状態の変更は1箇所で済み、あらゆるObserverが自動的に同期
2. 基本構成と実装例
✅ 抽象的なSubjectとObserver定義
class Observer:
def update(self, data):
raise NotImplementedError
class Subject:
def __init__(self):
self._observers = []
def attach(self, obs: Observer):
self._observers.append(obs)
def detach(self, obs: Observer):
self._observers.remove(obs)
def notify(self, data):
for obs in self._observers:
obs.update(data)
✅ 具象SubjectとObserverの実装
class DataSource(Subject):
def __init__(self):
super().__init__()
self._data = None
def set_data(self, value):
self._data = value
self.notify(self._data)
class Logger(Observer):
def update(self, data):
print(f"[LOG] Data updated to: {data}")
class Notifier(Observer):
def update(self, data):
print(f"[NOTIFY] Sending update for: {data}")
✅ 実行
source = DataSource()
source.attach(Logger())
source.attach(Notifier())
source.set_data("Event X")
3. ユースケース:現場での適用例
✅ フロントエンドにおけるUIバインディング
- 状態(Store)をSubjectとして定義
- 各ViewコンポーネントがObserverとして登録
- 状態が変更されるとUIが自動更新
✅ バッチ処理におけるログ通知の分離
job = BatchJob()
job.attach(SlackNotifier())
job.attach(DBLogger())
job.run()
→ ロジックと通知が疎結合になるため、構成変更が容易
✅ データパイプライン内でのHook実装
- データ流通の各ステップでObserverが登録され、特定条件下でアクションを実行
4. Python的に発展させる:デコレータで動的通知化
def observable(method):
def wrapper(self, *args, **kwargs):
result = method(self, *args, **kwargs)
self.notify(result)
return result
return wrapper
class SmartSource(Subject):
@observable
def set(self, value):
self._value = value
→ 通知ロジックを分離し、宣言的な実装に昇華可能
5. よくある誤用と対策
❌ Observerが状態を変更し、副作用ループが発生
→ ✅ 通知対象は「読み取り専用」にするか、再帰呼出しの防止策を明示的に設計
❌ オブザーバーが密に結合されている
→ ✅ Observerは update(data)
のみを受け取る設計とし、データ依存を減らす
❌ 無制限なObserver追加によりパフォーマンス劣化
→ ✅ detach()
を正しく設計し、ライフサイクルを明示的に制御
結語
オブザーバーパターンは、**リアクティブなシステム設計における「関心の分離」と「反応の自動化」**を担保する構造である。
- 状態の変化と振る舞いの連動を宣言的に設計
- コンポーネント間の結合度を最小限にし、テスト・拡張を容易にする
- GUI、通知、バッチ、非同期処理まで多様なドメインに対応
Pythonicとは、“状態の変化を手続きでなく構造で伝播させる”ことであり、
オブザーバーパターンはその思想を、シンプルかつパワフルに体現する設計である。