Dyuichi Blog

オブジェクト指向シリーズⅣ: デザインパターン [⑰ Observer]

概要

observeは日本語で「観察する」,observerは日本語で「観察者」という意味になる.Observerパターンは,あるオブジェクトの状態が変わったときに,そのオブジェクトに依存する他のオブジェクトに自動的に通知されるパターンである.

Observerパターンの主な要素は以下である.

  • Subject:Observerの追加,削除,通知するためのオブジェクトのインターフェース
  • ConcreteSubject:状態が変化した時にObserverに通知を送る,Subjectを実装したクラス
  • Observer:Subjectからの更新通知を受け取るオブジェクトのインターフェース
  • ConcreteObserver:Observerを実装したクラス

クラス図

画像が読み込まれない場合はページを更新してみてください。

実装例(Java)

javaimport java.util.ArrayList;
import java.util.List;

// Subject
interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

// Concrete Subject
class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    @Override
    public void addObserver(Observer observer) {
        if (!observers.contains(observer)) {
            observers.add(observer);
        }
    }
    @Override
    public void removeObserver(Observer observer) {
        if (observers.contains(observer)) {
            observers.remove(observer);
        }
    }
    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
}

// Observer
interface Observer {
    void update();
}

// Concrete Observer
class ConcreteObserverA implements Observer {
    @Override
    public void update() {
        System.out.println("ConcreteObserverA update");
    }
}

class ConcreteObserverB implements Observer {
    @Override
    public void update() {
        System.out.println("ConcreteObserverB update");
    }
}

// Client
public class ObserverPattern {
    public static void main(String[] args) {
        Subject subject = new ConcreteSubject();
        subject.addObserver(new ConcreteObserverA());
        subject.addObserver(new ConcreteObserverB());
        subject.notifyObservers();
    }
}

まとめ,所感

イベントリスナーとかで使われる模様.まあ確かに何かイベントが起きた ⇒ 状態が変わったと捉えることができる.

分散イベント処理システムが想像しやすい.実装例では,notifyObserversを直接クライアントから読んでいるが,Subject内で,新しくObserverが追加されたり削除されたりしたときに呼んでもいいかもしれない.

とにかくnotifyObserversをどのタイミングで実行するかが重要なポイントだと思われる.