ちゃんなるぶろぐ

エンジニア5年生🧑‍💻 オライリーとにらめっこする毎日。

【5分でわかる👀】TypeScriptでDesign Pattern〜Observer Pattern〜

どうも、ちゃんなるです!

今回は、Observer Patternを紹介します🖐️

Observer Patternは、オブジェクト間の依存関係を疎結合に保ちながら、状態の変更を通知するためのパターンです👀

概要

Observer Patternは、一つのオブジェクトが状態を持ち、その状態の変更を他のオブジェクト(オブザーバー)に通知するときに役立ちます。

オブザーバーは状態の変更に対して何らかのアクションを行うことができます。

今回示すプログラムの設計

あるオンラインショップで商品の在庫が変更されるたびに、在庫に関心を持つオブザーバー(顧客)に通知するシチュエーションを考えてみましょう🙋‍♀️

以下がクラス図とTypeScriptのサンプルコードです。

クラス図

サンプルコードのクラス図:Mermaid Live Editorで作成

クラス名 役割
Subject 被験者を表すインターフェイス
ConcreteSubject 被験者の具体的な実装。オブザーバーを管理し、在庫情報を保持し、在庫が変更された際にオブザーバーに通知する
Observer オブザーバーを表すインターフェイス。状態の変更に対するアップデートメソッドを持つ
ConcreteObserver オブザーバーの具体的な実装。顧客のメールアドレスを持ち、通知を受け取った際の処理を行う

サンプルコード

interface Subject {
    attach(observer: Observer): void;
    detach(observer: Observer): void;
    notify(): void;
}
class ConcreteSubject implements Subject {
    private observers: Observer[] = [];
    private inventory = 0;

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

    detach(observer: Observer): void {
        this.observers = this.observers.filter((obs) => obs !== observer);
    }

    notify(): void {
        this.observers.forEach((observer) => observer.update(this));
    }

    setInventory(inventory: number): void {
        this.inventory = inventory;
        this.notify();
    }

    getInventory(): number {
        return this.inventory;
    }
}
interface Observer {
    update(subject: Subject): void;
}
class ConcreteObserver implements Observer {
    private email: string;

    constructor(email: string) {
        this.email = email;
    }

    update(subject: Subject): void {
        console.log(
            `通知を受け取りました: ${
                this.email
            }, 在庫数は ${subject.getInventory()} です`
        );
    }
}

では、実際に使ってみましょう🖐️

const subject = new ConcreteSubject();

const observer1 = new ConcreteObserver('email1@example.com');
subject.attach(observer1);
subject.setInventory(10);

const observer2 = new ConcreteObserver('email2@example.com');
subject.attach(observer2);
subject.setInventory(20);

これにより、在庫が変更されるたびに、登録されたオブザーバー(顧客)に在庫数が通知されます👍

Observer Patternの使い道

  • あるオブジェクトの状態が変更されたときに、他のオブジェクトに自動的に通知する必要がある場合
  • オブジェクト間の依存関係を疎結合に保ちたい場合

組み合わせられるデザインパターン

  • Singleton Pattern: 組み合わせることで、システム全体で一つの被験者(例えば、設定情報)を共有し、変更通知を受け取ることができます。

chan-naru.hatenablog.com

  • Mediator Pattern: 組み合わせることで、複数のオブザーバー間の通信を効率的に管理し、オブザーバー同士の依存関係を最小限に抑えることができます。

chan-naru.hatenablog.com

まとめ

Observer Patternは、オブジェクト間の依存関係を疎結合に保ちながら、状態の変更を効率的に通知するためのデザインパターンです。

今回の記事では、具体的なシナリオとしてオンラインショップの在庫管理を例に挙げ、TypeScriptでの実装例を提供しました。

Observer Patternは多くのシナリオで有用であり、他のデザインパターンと組み合わせることで、より強力なソフトウェア設計が可能になります。

ぜひ、Observer Patternを活用して、疎結合な設計を実現しましょう!

参考文献

www.oreilly.com

en.wikipedia.org