Observerパターン

# はじめに
GoFデザインパターンの一つで振る舞いに関するパターンである
**Observerパターン**について見ていきたいと思います.

# Observerパターンとは
Observerパターンは,状態の変更を通知する側のオブジェクト(Subject)と,
その変更を監視する側のオブジェクト(Observer)が存在します.

これにより,オブジェクト間の依存関係を
1 対多(1つのSubject 対 複数のObservers)に定義することができます.

また,オブジェクト同士の疎結合を保ちながら,
状態変化をリアルタイムに伝える仕組みを提供します.

そのため,イベント駆動型プログラムやGUIなどで使用されます.

# Observerパターンの特徴
Observerパターンの基本構造は
**監視対象:Subject**と**観察者:Observer**の関係性を定義します.

これにより,オブジェクト間の依存を最小限にして,
あるオブジェクトの状態変更をほかのオブジェクトに通知することができます.

# Observerパターンの実装
Objectパターンを以下の構造を参考にして実装していきます.

これは,ClockがDigitalClockによって観察されており,時間が変更されるとDigitalClockがupdateメッセージを受け取ります.

その後,DigitalClockはClockに時間を尋ね,Clockから取得した時間を表示します.

![スクリーンショット 2025-01-04 010320.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586226/cd590a3a-2ae4-048f-35c7-939a77a0b570.png)

まず,構造のそれぞれの定義について見ていきます.

### Subject(観察対象)
- Observer(観察者)を登録・削除できるインタフェース
- 状態が変化したとき,登録されているすべてのObserverに通知

### Observer(観察者)
- Subjectからの通知を受け取るためのインタフェース
- Subjectの状態に応じて自身の動作を更新

### Clock(具体的な観察対象)
- Subjectの具体的な実装
- 自分自身の状態を管理し,状態の変化時に通知

### DigitalClock(具体的な観察者)
- Observerの具体的な実装
- Subjectから通知を受け取り,自分の状態を更新

## ソースコード
以下がそれぞれのソースコードと出力例になります.

```java:Subject.java
import java.util.ArrayList;
import java.util.List;

public class Subject {
    private final List<Observer> observers = new ArrayList<>();

    // Observerを登録
    public void register(Observer observer) {
        observers.add(observer);
    }

    // Observerを解除
    public void unregister(Observer observer) {
        observers.remove(observer);
    }

    // 全Observerに通知
    public void notifyObservers(int hours, int minutes, int seconds) {
        for (Observer observer : observers) {
            observer.update(hours, minutes, seconds);
        }
    }
}
```

```java:Observer.java
public interface Observer {
    void update(int hours, int minutes, int seconds);
}
```

```java:Clock.java
class Clock {
    private int hours;
    private int minutes;
    private int seconds;
    private final List<Observer> observers = new ArrayList<>();

    // Observerを登録
    public void register(Observer observer) {
        observers.add(observer);
    }

    // Observerを削除
    public void unregister(Observer observer) {
        observers.remove(observer);
    }

    // 状態が変わったときに通知
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(hours, minutes, seconds);
        }
    }

    // 時間を設定し、通知を送信
    public void setTime(int hours, int minutes, int seconds) {
        this.hours = hours;
        this.minutes = minutes;
        this.seconds = seconds;
        notifyObservers();
    }
}
```

```java:DigitalClock.java
public class DigitalClock implements Observer {
    private final String name;

    public DigitalClock(String name) {
        this.name = name;
    }

    @Override
    public void update(int hours, int minutes, int seconds) {
        System.out.println(name + " - Current time: " + String.format("%02d:%02d:%02d", hours, minutes, seconds));
    }
}
```

```java:Main.java
public class Main {
    public static void main(String[] args) {
        // Clockオブジェクト（観察対象）を作成
        Clock clock = new Clock();

        // DigitalClockオブジェクト（観察者）を作成して登録
        DigitalClock digitalClock1 = new DigitalClock("DigitalClock1");
        DigitalClock digitalClock2 = new DigitalClock("DigitalClock2");
        clock.register(digitalClock1);
        clock.register(digitalClock2);

        // 時刻を設定して通知
        clock.setTime(10, 30, 45);
        clock.setTime(12, 15, 20);

        // DigitalClock1を解除
        clock.unregister(digitalClock1);

        // 別の時刻を設定して通知
        clock.setTime(14, 50, 10);
    }
}
```

```sql:出力例
DigitalClock1 - Current time: 10:30:45
DigitalClock2 - Current time: 10:30:45
DigitalClock1 - Current time: 12:15:20
DigitalClock2 - Current time: 12:15:20
DigitalClock2 - Current time: 14:50:10
```

# Observerパターンのメリットとデメリット
### メリット
1. **拡張性**: 新しいObserverを簡単に追加できます
2. **柔軟性**: SubjectとObserverの間で疎結合を実現できます
3. **リアルタイム性**: 状態変化が即座に反映されます

### デメリット
1. **通知のコスト**: Observerが多いと,通知処理に時間がかかってしまいます

# 参考
https://www.issoh.co.jp/tech/details/3565/

[アジャイルソフトウェア開発の奥義](https://www.amazon.co.jp/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA%E3%81%AE%E5%A5%A5%E7%BE%A9-%E7%AC%AC2%E7%89%88-%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E9%96%8B%E7%99%BA%E3%81%AE%E7%A5%9E%E9%AB%84%E3%81%A8%E5%8C%A0%E3%81%AE%E6%8A%80-%E3%83%AD%E3%83%90%E3%83%BC%E3%83%88%E3%83%BBC%E3%83%BB%E3%83%9E%E3%83%BC%E3%83%81%E3%83%B3/dp/4797347783)