Observer パターン:イベント通知
株価システムで Observer を実装し、イベントの生成側と利用側を分離します。
「Observer パターン:イベント通知」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
Observer の目的
Observer(Publish-Subscribe とも呼ばれます)は、1対多の依存関係を定義します。サブジェクトの状態が変化すると、登録されているすべてのオブザーバーに自動的に通知されます。
サブジェクトとオブザーバーのインターフェース
サブジェクトはオブザーバーのリストを管理し、通知を送ります。オブザーバーは update メソッドを実装してイベントに反応します。
public interface Observer {
void update(String event, Object data);
}
public interface Subject {
void addObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers(String event, Object data);
}具象サブジェクト: 株価ティッカー
サブジェクトは状態を保持し、状態が変化するたびに notifyObservers を呼び出します。また、オブザーバーのリストを管理します。
public class StockTicker implements Subject {
private final List<Observer> observers = new ArrayList<>();
private double price;
public void addObserver(Observer o) { observers.add(o); }
public void removeObserver(Observer o) { observers.remove(o); }
public void setPrice(double p) {
this.price = p;
notifyObservers("PRICE_CHANGED", p);
}
public void notifyObservers(String ev, Object data) {
for (Observer o : observers) o.update(ev, data);
}
}具象オブザーバー
各オブザーバーは、同じ通知に対してそれぞれ異なる反応をします。サブジェクトを変更せずに、実行時にオブザーバーを追加できます。
public class AlertSystem implements Observer {
public void update(String ev, Object data) {
if ((double) data < 100) System.out.println("ALERT: Low price!");
}
}
public class Logger implements Observer {
public void update(String ev, Object data) {
System.out.println("LOG: " + ev + " = " + data);
}
}オブザーバーの接続
サブジェクトにオブザーバーを登録します。サブジェクトが変化すると、登録されたすべてのオブザーバーが反応します。更新の受信を停止するには登録を解除します。
StockTicker ticker = new StockTicker();
ticker.addObserver(new AlertSystem());
ticker.addObserver(new Logger());
ticker.setPrice(95.5); // both observers notifiedjava.util.Observable — 非推奨
JDK には java.util.Observable と java.util.Observer がありましたが、Java 9 以降では非推奨です。独自に実装するか、RxJava や Project Reactor などのリアクティブライブラリを使用してください。
PropertyChangeListener
JavaBeans には PropertyChangeSupport が用意されています。これは Bean のプロパティ変更に対応する組み込みのオブザーバー機構で、Swing や JavaFX で広く使われています。
public class Model {
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private int value;
public void addPropertyChangeListener(PropertyChangeListener l) { pcs.addPropertyChangeListener(l); }
public void setValue(int v) {
int old = this.value; this.value = v;
pcs.firePropertyChange("value", old, v);
}
}Consumer を使った関数型オブザーバー
専用のインターフェースを定義する代わりに、軽量なオブザーバーとして Consumer<T> を使えます。単純なイベントコールバックに最適です。
List<Consumer<Double>> listeners = new ArrayList<>();
listeners.add(p -> { if (p < 100) System.out.println("Low price"); });
listeners.add(p -> System.out.println("Price: " + p));
double newPrice = 95.5;
listeners.forEach(l -> l.accept(newPrice));Observer と Event Bus の比較
Event Bus(Guava EventBus など)は、サブジェクトとオブザーバーをさらに疎結合にします。サブジェクトは誰がリッスンしているかを知らずに、Event Bus にイベントをポストできます。オブザーバーはメソッドのアノテーションによって購読します。
// Guava EventBus example
EventBus bus = new EventBus();
bus.register(new Logger()); // subscribe
bus.post(new PriceEvent(95.5)); // publishObserver におけるスレッドセーフティ
複数のスレッドからオブザーバーを追加・削除できる場合は、synchronized でリストを保護するか、通知が多い処理では CopyOnWriteArrayList を使用してください。
private final List<Observer> observers = new CopyOnWriteArrayList<>();メモリリークの回避
オブザーバーのリストに強い参照を保持すると、GC がオブザーバーを回収できなくなります。WeakReference<Observer> を使うか、不要になったオブザーバーの登録を必ず解除してください。
実際のフレームワークにおける Observer
Spring の ApplicationEventPublisher、Android LiveData、JavaFX のプロパティは、いずれも異なる抽象度で実装された Observer パターンです。
確認問題
Observer パターンの主な利点は何ですか。
まとめ
Observer は、1対多の通知チェーンを定義します。インターフェースまたは関数型の Consumer を使って実装できます。スレッドセーフティには CopyOnWriteArrayList を使用し、メモリリークを防ぐためにオブザーバーの登録を必ず解除してください。
よくある質問
「Observer パターン:イベント通知」レッスンは無料ですか?
はい。「Observer パターン:イベント通知」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「Observer パターン:イベント通知」で何を学びますか?
株価システムで Observer を実装し、イベントの生成側と利用側を分離します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「Observer パターン:イベント通知」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Observer パターン:イベント通知
- Strategy パターン:交換可能なアルゴリズム
- Command パターン:操作のカプセル化
- Template Method:アルゴリズムの骨格定義