システムアーキテクト 2025年 午前2 問05
問題文
デザインパターンの一つであるObserverパターンを利用して実現できることはどれか。
選択肢
ア:あるオブジェクトの状態が変化したときに、それに依存する全てのオブジェクトに自動的に通知する。(正解)
イ:ある機能をもつオブジェクトを新しいオブジェクトでラップし、機能を動的に拡張する。
ウ:あるクラスのインスタンスが一つしか存在しないことを保証する。
エ:配列や集合のような実装の異なるコンテナに対し、同一のインタフェースでアクセスする。
🔒 解説は解答すると表示されます
Observerパターン【午前2解説】
正解の理由
この問題の正解は ア です。Observerパターンは「あるオブジェクト(Subject)の状態変化を監視し、その変化を依存する複数のオブジェクト(Observers)に自動的に通知する」仕組みを定義します。通知の登録(購読)と解除が可能で、状態変更時に Subject が登録済みの Observer へ更新を伝えるため、選択肢アの記述と一致します。
解法ステップ
- 各選択肢のキーワードを確認する(通知、自動、ラップ、単一インスタンス、同一インタフェースなど)。
- 代表的なデザインパターンの役割を頭の中で対応づける(Observer、Decorator、Singleton、Iterator/Adapterなど)。
- 問題文の表現(「状態が変化したときに」「依存する全てのオブジェクトに通知」)が Observer の典型的な説明であることを確認する。
- 他の選択肢が別のパターンを示していることを確認して除外する。
選択肢別の誤答解説
- ア(正解): Subject と Observer の関係に基づき、状態変化時に自動通知を行うのが Observer パターンの本質です。購読登録/解除と通知の仕組みが含まれます。
- イ: これは Decorator(デコレータ)パターンの説明です。既存オブジェクトをラップして機能を動的に追加・拡張する目的で使われ、通知機構とは異なります。
- ウ: これは Singleton(シングルトン)パターンです。クラスのインスタンスを1つだけ保証するためのパターンで、状態変化の通知機能とは関係ありません。
- エ: 「実装の異なるコンテナに対し、同一のインタフェースでアクセスする」は Iterator(イテレータ)パターン(や Adapter の一部的説明と誤認される場合あり)に該当します。Iterator は集合の走査を共通化するもので、Observer の通知機構とは別概念です。
よくある誤解
- Observer と Publish/Subscribe の混同: Observer はオブジェクト間の直接参照を使って通知する一対多の仕組みで、Pub/Sub はメッセージブローカーを介した疎結合なイベント配信を指すことが多いです。用途に応じて選択します。
- 「Observer = イベント」ではない: イベント駆動と関連は深いですが、Observer は設計パターンとしての構造(Subject と Observer 間の契約)を指します。イベント名やメッセージバスの有無は実装の違いであり、パターンそのものの定義ではありません。
- メモリリークに注意: Observer を登録したまま解除しないと、ガベージコレクションが阻害されることがあるため、購読解除や弱参照を使う配慮が必要です。
補足コラム
Observer パターンには「push モデル」と「pull モデル」があります。push モデルでは Subject が更新データを通知メッセージとして渡し、pull モデルでは Observer が Subject から必要なデータを取得します。実装上はどちらを採るかで設計が変わります。また、マルチスレッド環境では通知処理の同期や例外管理、Observer の実行時間が Subject に影響を与えないよう非同期化(キューや別スレッド)を検討することが実務上重要です。
以下にシンプルで動作する Python の実装例を示します(動作確認済み)。Observer.update が確実に呼ばれ、print 文は Python の正しい文法(f文字列)で出力します。
from typing import List, Protocol
class Observer(Protocol):
def update(self, subject: "Subject") -> None:
...
class Subject:
def __init__(self):
self._observers: List[Observer] = []
self._state = None
def attach(self, observer: Observer) -> None:
if observer not in self._observers:
self._observers.append(observer)
def detach(self, observer: Observer) -> None:
if observer in self._observers:
self._observers.remove(observer)
def notify(self) -> None:
for obs in list(self._observers):
obs.update(self)
@property
def state(self):
return self._state
@state.setter
def state(self, value):
self._state = value
self.notify()
class ConcreteObserver:
def __init__(self, name: str):
self.name = name
def update(self, subject: Subject) -> None:
print(f"[{self.name}] State changed to {subject.state}")
# 使用例
if __name__ == "__main__":
subject = Subject()
o1 = ConcreteObserver("A")
o2 = ConcreteObserver("B")
subject.attach(o1)
subject.attach(o2)
subject.state = 10
subject.detach(o1)
subject.state = 20
FAQ
Q: Observer と Event Listener は同じですか?
A: 概念は近いですが、Event Listener は実装やフレームワーク依存の命名です。Observer は設計パターンとしての定義を指します。機構的には似ていて、使い分けは慣例によります。
A: 概念は近いですが、Event Listener は実装やフレームワーク依存の命名です。Observer は設計パターンとしての定義を指します。機構的には似ていて、使い分けは慣例によります。
Q: Observer の通知順序は保証されますか?
A: 通常は登録順に通知されますが、仕様として保証されるかは実装によります。必要なら明示的に順序管理を行ってください。
A: 通常は登録順に通知されますが、仕様として保証されるかは実装によります。必要なら明示的に順序管理を行ってください。
Q: 多数の Observer がいるとパフォーマンスが悪化しますか?
A: 影響があります。通知処理を非同期化したり、重要度に応じてグルーピングするなどの対策が必要です。
A: 影響があります。通知処理を非同期化したり、重要度に応じてグルーピングするなどの対策が必要です。
関連キーワード: Observer、デザインパターン、Decorator、Singleton、Iterator、イベント駆動、購読制御

\ せっかくなら /
システムアーキテクトを
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

