第06回: Observerパターン — 「通知する側」と「受け取る側」を切り離す

章: 第1章: オブジェクト指向の深化

「注文完了したら〇〇する」が増え続ける問題

注文完了後にメールを送る。さらにSlackに通知する。さらに在庫を更新する。さらに分析ログを記録する——。

こうした処理を「注文完了クラス」に直接書いていくと、どんどん肥大化します。また、新しい処理を追加するたびに注文クラスを変更しなければなりません

Observerパターンは「イベントを発行する側」と「イベントを受け取る側」を分離することで、発行側のコードを一切変えずに新しい処理を追加できる設計です。

Observerパターンの実装


<?php
// オブザーバーの契約
interface Observer {
    public function update(string $event): void;
}

// イベントを発行する側(Subject)
class EventEmitter {
    private array $listeners = [];

    public function on(Observer $o): void {
        $this->listeners[] = $o;
    }

    public function emit(string $event): void {
        foreach ($this->listeners as $o) {
            $o->update($event);
        }
    }
}

// 具体的なオブザーバー
class EmailNotifier implements Observer {
    public function update(string $event): void {
        echo "メールを送信: {$event}";
    }
}
class SlackNotifier implements Observer {
    public function update(string $event): void {
        echo "Slackに通知: {$event}";
    }
}

// 使い方
$emitter = new EventEmitter();
$emitter->on(new EmailNotifier());
$emitter->on(new SlackNotifier());
$emitter->emit('order.completed'); // 両方に通知される

ベタ書き vs Observerパターン

観点 ベタ書き(直接呼び出し) Observerパターン
新しい処理の追加 発行クラスを変更する オブザーバーを登録するだけ
発行クラスの責務 通知先を全部知っている 「発火する」だけに集中
テスト 全通知先が混在 各オブザーバーを独立してテスト
処理の有効化/無効化 コードを変更 登録・解除で制御

チェックポイント: Laravelの event() / listen() はObserverパターンの実装です。フレームワークでよく使う仕組みを自分で作れると理解が深まります。

PHPのSplObserverを使う場合

PHPには標準で SplObserver / SplSubject インターフェイスがあります。シンプルなケースでは自作せずこれを使えます。


<?php
class Order implements SplSubject {
    private SplObjectStorage $observers;
    public function __construct() {
        $this->observers = new SplObjectStorage();
    }
    public function attach(SplObserver $observer): void {
        $this->observers->attach($observer);
    }
    public function detach(SplObserver $observer): void {
        $this->observers->detach($observer);
    }
    public function notify(): void {
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }
}

チェックポイント: 処理の追加・削除が「発信側のコードを変えずにできる」ことがObserverパターンの核心です。

まとめ & 次のステップ

  • Observerパターンは「発行側」と「受け取り側」を分離し、拡張に強い設計を実現する
  • 新しい処理を追加するとき、発行クラスを変更しなくて済む
  • LaravelのイベントシステムはObserverパターンをフレームワークレベルで提供している

次回はRepositoryパターンを学びます。「データの取得・保存ロジック」をビジネスロジックから切り離す設計手法です。

Related Articles