Pythonで実装するObserverパターン：イベント通知の仕組みを構築する


## 概要

**Observer（オブザーバー）パターン**は、  
あるオブジェクト（Subject）の状態変化を、**それに依存する複数のオブザーバー（Observer）に自動で通知する**ためのデザインパターンである。

イベント駆動型の設計、UI更新、リアルタイム通知など、**状態変化に対する反応的な処理を整理するために極めて有効**である。

---

## 1. なぜObserverが必要か？

### ❌ 状態変化を検知するたびに明示的に通知処理を呼び出す

```python
user.set_status("online")
notifier.send_email()
ui.update_status()
logger.log()
```

→ 通知処理が**散在し、依存性が高く、変更に弱い構造**

---

### ✅ 状態の変更を一元化し、自動で関係者に通知する構造へ

```python
user.set_status("online")
# → 登録されたすべてのオブザーバーが反応
```

→ **送信者（Subject）と受信者（Observer）の疎結合化を実現**

---

## 2. 基本構造

### ✅ Observerインターフェース

```python
class Observer:
    def update(self, subject):
        raise NotImplementedError
```

---

### ✅ Subject（通知元）

```python
class Subject:
    def __init__(self):
        self._observers = set()

    def attach(self, observer: Observer):
        self._observers.add(observer)

    def detach(self, observer: Observer):
        self._observers.discard(observer)

    def notify(self):
        for observer in self._observers:
            observer.update(self)
```

---

### ✅ ConcreteSubject（状態を持つ具体クラス）

```python
class User(Subject):
    def __init__(self, name):
        super().__init__()
        self.name = name
        self._status = "offline"

    def set_status(self, status):
        self._status = status
        self.notify()

    def get_status(self):
        return self._status
```

---

### ✅ ConcreteObserver（通知を受けて反応する側）

```python
class Logger(Observer):
    def update(self, subject):
        print(f"[Logger] {subject.name} is now {subject.get_status()}")

class Notifier(Observer):
    def update(self, subject):
        print(f"[Notifier] Sending notification: {subject.name} is {subject.get_status()}")
```

---

### ✅ 使用例

```python
user = User("Alice")
logger = Logger()
notifier = Notifier()

user.attach(logger)
user.attach(notifier)

user.set_status("online")
user.set_status("away")
```

出力:
```
[Logger] Alice is now online
[Notifier] Sending notification: Alice is online
[Logger] Alice is now away
[Notifier] Sending notification: Alice is away
```

---

## 3. Python的応用：デコレータ的シグナルパターン

```python
class Signal:
    def __init__(self):
        self._handlers = []

    def connect(self, func):
        self._handlers.append(func)

    def emit(self, *args, **kwargs):
        for handler in self._handlers:
            handler(*args, **kwargs)

status_changed = Signal()

def send_alert(status):
    print(f"[Alert] User is {status}")

status_changed.connect(send_alert)
status_changed.emit("busy")
```

→ **DjangoのSignal風の実装により、柔軟なリアクティブ処理が可能**

---

## 4. 実務ユースケース

### ✅ GUIの状態変化によるUI部品の自動更新

→ ボタン押下、フォーム入力、画面遷移時の**リアルタイム同期**

---

### ✅ SNSやチャットアプリの通知システム

→ フォロー中ユーザーの行動に対する**非同期通知**

---

### ✅ IoTセンサーデータのストリーミング処理

→ センサー状態を**監視・ログ・UIに自動反映**

---

### ✅ モデルの状態変更に応じたView更新（MVC）

→ モデルが変更されると、**登録されたViewにイベント通知が飛ぶ**

---

## 5. よくある誤用と対策

### ❌ 通知処理の中で状態変更を行い、無限ループ発生

→ ✅ **再帰的な通知チェーンは設計的に遮断する**

---

### ❌ ObserverがSubjectの内部構造に依存しすぎる

→ ✅ `update(subject)`の中で**最低限のインターフェースだけを使う**

---

### ❌ オブザーバーの登録解除を忘れるとメモリリーク

→ ✅ **`detach()`の実行や弱参照による管理を検討**

---

## 結語

**Observerパターンとは、“変化を知るべき存在に、通知の流れを正しく届ける設計技法”である。**

- 状態変化に伴う反応処理を**構造として設計し、通知の流れを一元化**  
- 依存を減らしつつ、**リアクティブなアプリケーション構造を可能に**  
- Pythonではインターフェース不要の柔軟な実装が可能で、**Signal/Slot/Hookなど多様な形で活用できる**

**Pythonicとは、“リアルタイムの変化に優雅に反応すること”。  
Observerパターンはその変化の波を、秩序と意志を持って伝える構造である。**