JavaScriptのObserverとは?

JavaScriptのObserverとは?

JavaScriptのObserverとは?

Observerパターンは、オブジェクト指向プログラミングにおけるデザインパターンの一つで、オブジェクト間の一対多の依存関係を定義します。このパターンでは、Subjectと呼ばれるオブジェクトの状態が変化すると、Observerと呼ばれる依存するオブジェクトに自動的に通知が送られます。これにより、Subjectの状態が変化したときに、Observerは自身の状態を更新したり、適切な処理を実行したりすることができます。

Observerパターンの構成要素

Observerパターンは、主に以下の2つの構成要素で成り立っています。

構成要素 説明
Subject(監視対象) 状態の変化をObserverに通知するオブジェクト。Observerのリストを保持し、状態が変化したときに通知を送信する役割を担います。
Observer(監視者) Subjectの状態変化の通知を受け取るオブジェクト。Subjectの状態変化に応じて、自身に何らかの処理を実行します。

JavaScriptにおけるObserverパターン

JavaScriptでは、Observerパターンを比較的簡単に実装することができます。Observerは、Subjectからの更新を受け取りたいオブジェクトです。ObserverはObserverインターフェースを実装します。このインターフェースには、Subjectが状態が変化したときに呼び出される`update()`メソッドを持つ、1つのメソッドしかありません。


interface Observer {
  update(subject: Subject): void;
}
  

Subjectは、状態を保持し、Observerに状態の変化を通知するオブジェクトです。SubjectはSubjectインターフェースを実装します。このインターフェースには、Observerを追加および削除するためのメソッドと、Observerに状態の変化を通知するためのメソッドがあります。


interface Subject {
  attach(observer: Observer): void;
  detach(observer: Observer): void;
  notifyObservers(): void;
}
  

以下は、JavaScriptでObserverパターンを実装する例です。


class ConcreteSubject implements Subject {
  private observers: Observer[] = [];
  private state: number;

  getState(): number {
    return this.state;
  }

  setState(state: number): void {
    this.state = state;
    this.notifyObservers();
  }

  attach(observer: Observer): void {
    this.observers.push(observer);
  }

  detach(observer: Observer): void {
    const index = this.observers.indexOf(observer);
    if (index !== -1) {
      this.observers.splice(index, 1);
    }
  }

  notifyObservers(): void {
    for (const observer of this.observers) {
      observer.update(this);
    }
  }
}

class ConcreteObserver implements Observer {
  update(subject: Subject): void {
    console.log('Observer: Subject state changed to ' + subject.getState());
  }
}

// 利用例
const subject = new ConcreteSubject();
const observer1 = new ConcreteObserver();
const observer2 = new ConcreteObserver();

subject.attach(observer1);
subject.attach(observer2);

subject.setState(10); // Observer: Subject state changed to 10 (observer1とobserver2の両方に通知)
subject.setState(20); // Observer: Subject state changed to 20 (observer1とobserver2の両方に通知)

subject.detach(observer1);

subject.setState(30); // Observer: Subject state changed to 30 (observer2のみに通知)
  

Observerパターンのメリット

  • 疎結合:SubjectとObserverは互いに依存せず、インターフェースを通してのみやり取りを行います。そのため、一方を変更しても、他方に影響を与えることなく変更することができます。
  • 柔軟性:SubjectはObserverの数や種類を気にすることなく、状態の変化を通知することができます。Observerは必要な通知だけを受け取ることができます。
  • 再利用性:SubjectとObserverは独立して再利用することができます。

Observerパターンのユースケース

Observerパターンは、以下のようなケースで有効です。

  • あるオブジェクトの状態が変化したときに、他のオブジェクトに通知を送りたい場合
  • オブジェクト間の依存関係を疎結合に保ちたい場合
  • 柔軟で拡張性の高いシステムを構築したい場合

参考資料

Q&A

Q1: Observerパターンは、どのような場合に有効なデザインパターンですか?

A1: あるオブジェクトの状態変化に応じて、他のオブジェクトに通知を送りたい場合や、オブジェクト間の依存関係を疎結合に保ちたい場合に有効なデザインパターンです。例えば、ニュースフィードの更新やチャットアプリケーションのメッセージ受信などに利用されます。

Q2: JavaScriptでObserverパターンを実装するには、どのような方法がありますか?

A2: JavaScriptでObserverパターンを実装するには、クラスやプロトタイプを用いる方法があります。上記の実装例では、class構文を用いてSubjectとObserverを実装しています。状態の変化を通知する`notifyObservers`メソッドでは、登録されているObserverに対して順番に`update`メソッドを呼び出しています。

Q3: Observerパターンを使用する際の注意点は何ですか?

A3: Observerパターンを使用する際の注意点は、循環参照を避けることです。SubjectとObserverが互いに参照し合っていると、メモリリークが発生する可能性があります。循環参照を避けるためには、WeakMapやWeakSetなどの弱参照を使う方法があります。

その他の参考記事:jquery observer