【ITニュース解説】Observer Design Pattern
2025年10月05日に「Dev.to」が公開したITニュース「Observer Design Pattern」について初心者にもわかりやすく解説しています。
ITニュース概要
オブザーバーパターンは、あるオブジェクトの状態が変わると、それを監視する複数のオブジェクトに自動で知らせて更新させる仕組みだ。ECサイトの価格変更やSNSのリアルタイム更新のように、複数の場所へ同時に情報を伝え、システムを柔軟に構築するのに役立つ。
ITニュース解説
オブザーバーデザインパターンとは、システムの複数の部分が互いに協力し合い、情報をスムーズにやり取りするための仕組みの一つである。AmazonやフリップカートのようなECサイトで、商品の価格が下がったり、在庫が変動したりしたときに、ウェブサイトの表示やスマートフォンのアプリに瞬時に情報が反映され、通知が届くのは、まさにこのオブザーバーパターンが活用されているからである。また、SNSで自分の投稿に「いいね」がついた際に、リアルタイムでフィードに表示されるのも同様の仕組みである。
このパターンの核心は、「オブジェクト間のコミュニケーションと同期」にある。あるオブジェクトの状態が変化したときに、その変化に依存する他のすべてのオブジェクトが自動的に更新されるようにする。これは、まるでデジタルな連鎖反応のようで、一つのイベントが複数の更新を順次引き起こすものの、システム全体が密接に結合することなく、柔軟に動作できる点が特徴だ。
具体的には、株価アプリでのリアルタイム更新、チャットシステム、ライブダッシュボード、そして様々なリアルタイム通知など、常に最新の情報を提供する必要がある現代のリアクティブシステムの基盤として広く利用されている。
このパターンは、大きく分けて「監視される側(SubjectまたはObservable)」と「監視する側(Observer)」という二つの役割で構成される。監視される側は自分の状態が変化したときに、登録されているすべての監視する側にその変化を通知する責任を持つ。一方、監視する側は、通知を受け取ったときに、自身を適切に更新する。
Javaのコード例を見てみよう。まず、このパターンの基盤となる抽象クラスが定義されている。
Observable クラスは「監視される側」の抽象的な表現である。このクラスは、自分を監視するObserverオブジェクトをリストで保持している。具体的には、addObserverメソッドで監視者をリストに追加し、removeObserverメソッドでリストから削除できる。最も重要なのはnotifyObserversメソッドで、これは監視される側の状態が変化したときに呼び出され、登録されているすべてのObserverのupdateメソッドを呼び出すことで、変化を通知する役割を担う。ここでupdateメソッドにthis(自分自身)と変化の内容を表すargを渡すことで、どのObservableがどのように変化したかをObserverに伝える。
次に、Observer クラスは「監視する側」の抽象的な表現である。このクラスには、updateという抽象メソッドが一つだけ定義されている。これは、Observableから通知が来たときに、具体的にどのような処理を行うかを、Observerを継承する具体的なクラスが実装することになる。
Product クラスは、具体的な商品情報を保持するためのシンプルなデータクラスである。商品ID、名前、価格、在庫数といった属性を持ち、これらの情報を取得したり(getter)、価格や在庫を更新したり(setter)する機能を持つ。このクラス自体はオブザーバーパターンとは直接関係なく、単に管理対象のデータを示している。
ProductInventory クラスは、Observableクラスを継承しており、これが具体的な「監視される側」となる。このクラスは、商品のIDをキーとしてProductオブジェクトを管理するMapを持っている。addProductメソッドで新しい商品を追加したり、updatePriceメソッドで商品の価格を更新したり、updateStockメソッドで在庫数を変更したりする際に、それぞれ内部でnotifyObserversメソッドを呼び出している。これにより、ProductInventoryの状態(商品の追加、価格変更、在庫変更)に変化があったことを、登録されているすべてのObserverに通知する。通知の内容として、追加時は文字列を、価格や在庫の更新時は更新されたProductオブジェクト自体を渡している点が特徴だ。
WebsitePlatform、MobileAppPlatform、KioskPlatformの各クラスは、いずれもObserverクラスを継承しており、これらが具体的な「監視する側」となる。それぞれのクラスは、updateメソッドをオーバーライドして、ProductInventoryからの通知を受け取った際の具体的な処理を実装している。updateメソッドでは、引数として渡されたargがProductオブジェクトなのか、それともString(メッセージ)なのかをチェックし、通知の内容に応じて適切なメッセージをコンソールに出力している。例えば、Productオブジェクトが渡された場合は、その商品の最新の価格や在庫を表示し、Stringが渡された場合は、その文字列メッセージを表示する。これにより、一つのProductInventoryの状態変化が、ウェブサイト、モバイルアプリ、店頭キオスクといった異なるプラットフォームの表示に、それぞれ適した形でリアルタイムに反映される仕組みが実現されている。
最後に、ECommerceObserverMain クラスは、このオブザーバーパターンがどのように動作するかを示すメインプログラムである。ここではまず、ProductInventoryのインスタンスを生成し、これが「監視される側」となる。次に、WebsitePlatform、MobileAppPlatform、KioskPlatformのインスタンスをそれぞれ生成し、これらが「監視する側」となる。これらの監視する側オブジェクトは、inventory.addObserverメソッドを使ってProductInventoryに登録される。
その後、iphoneとmacbookという二つの商品がinventory.addProductメソッドでProductInventoryに追加される。この時点ですでに、ProductInventoryは登録されているすべての監視者に「新しい商品が追加された」という通知を送るため、各プラットフォームがその情報を表示する。
続いて、inventory.updatePrice("P001", 75999)が呼び出され、iPhoneの価格が更新される。すると、ProductInventoryは再び登録されているすべての監視者(ウェブサイト、モバイルアプリ、キオスク)に、更新されたProductオブジェクトを引数として通知を送る。各監視者はこの通知を受け取り、それぞれのupdateメソッド内で最新のiPhoneの価格情報を表示する。同様に、inventory.updateStock("P002", 3)が呼び出されると、MacBook Airの在庫情報が更新され、それが瞬時に各プラットフォームに反映される様子が確認できる。
このように、オブザーバーパターンは、システム内の特定のオブジェクト(この例ではProductInventory)の状態変化を、その変化に興味を持つ複数のオブジェクト(WebsitePlatform、MobileAppPlatformなど)に自動的に伝え、同期を保つための強力で柔軟な方法を提供する。これにより、コードの密結合を防ぎ、システムの拡張性や保守性を向上させながら、現代の要求されるリアルタイムな情報更新を実現しているのである。