Observer_パターン
[Wikipedia|▼Menu]
.mw-parser-output .ambox{border:1px solid #a2a9b1;border-left:10px solid #36c;background-color:#fbfbfb;box-sizing:border-box}.mw-parser-output .ambox+link+.ambox,.mw-parser-output .ambox+link+style+.ambox,.mw-parser-output .ambox+link+link+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+style+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+link+.ambox{margin-top:-1px}html body.mediawiki .mw-parser-output .ambox.mbox-small-left{margin:4px 1em 4px 0;overflow:hidden;width:238px;border-collapse:collapse;font-size:88%;line-height:1.25em}.mw-parser-output .ambox-speedy{border-left:10px solid #b32424;background-color:#fee7e6}.mw-parser-output .ambox-delete{border-left:10px solid #b32424}.mw-parser-output .ambox-content{border-left:10px solid #f28500}.mw-parser-output .ambox-style{border-left:10px solid #fc3}.mw-parser-output .ambox-move{border-left:10px solid #9932cc}.mw-parser-output .ambox-protection{border-left:10px solid #a2a9b1}.mw-parser-output .ambox .mbox-text{border:none;padding:0.25em 0.5em;width:100%;font-size:90%}.mw-parser-output .ambox .mbox-image{border:none;padding:2px 0 2px 0.5em;text-align:center}.mw-parser-output .ambox .mbox-imageright{border:none;padding:2px 0.5em 2px 0;text-align:center}.mw-parser-output .ambox .mbox-empty-cell{border:none;padding:0;width:1px}.mw-parser-output .ambox .mbox-image-div{width:52px}html.client-js body.skin-minerva .mw-parser-output .mbox-text-span{margin-left:23px!important}@media(min-width:720px){.mw-parser-output .ambox{margin:0 10%}}

この記事には複数の問題があります。改善やノートページでの議論にご協力ください。

出典がまったく示されていないか不十分です。内容に関する文献や情報源が必要です。(2015年10月)


脚注による出典や参考文献の参照が不十分です。脚注を追加してください。(2021年8月)
出典検索?: "Observer パターン" ? ニュース ・ 書籍 ・ スカラー ・ CiNii ・ J-STAGE ・ NDL ・ dlib.jp ・ ジャパンサーチ ・ TWL

.mw-parser-output .imbox{margin:4px 0;border-collapse:collapse;border:3px solid #36c;background-color:#fbfbfb;box-sizing:border-box}.mw-parser-output .imbox .mbox-text .imbox{margin:0 -0.5em;display:block}.mw-parser-output .imbox-speedy{border:3px solid #b32424;background-color:#fee7e6}.mw-parser-output .imbox-delete{border:3px solid #b32424}.mw-parser-output .imbox-content{border:3px solid #f28500}.mw-parser-output .imbox-style{border:3px solid #fc3}.mw-parser-output .imbox-move{border:3px solid #9932cc}.mw-parser-output .imbox-protection{border:3px solid #a2a9b1}.mw-parser-output .imbox-license{border:3px solid #88a;background-color:#f7f8ff}.mw-parser-output .imbox-featured{border:3px solid #cba135}.mw-parser-output .imbox .mbox-text{border:none;padding:0.25em 0.9em;width:100%;font-size:90%}.mw-parser-output .imbox .mbox-image{border:none;padding:2px 0 2px 0.9em;text-align:center}.mw-parser-output .imbox .mbox-imageright{border:none;padding:2px 0.9em 2px 0;text-align:center}.mw-parser-output .imbox .mbox-empty-cell{border:none;padding:0;width:1px}.mw-parser-output .imbox .mbox-invalid-type{text-align:center}@media(min-width:720px){.mw-parser-output .imbox{margin:4px 10%}}

この記事内にあるすべての画像は、ベクターイメージである SVG ファイルとして再作成されるべきです。これにはいくつかの利点があります。詳しくはWikipedia:SVGへの乗り換えを参照してください。この画像の SVG 形式がすでに利用可能である場合は、アップロードしてください。アップロード後、この画像にあるこのテンプレートを{{SVG版利用可能|新しい画像ファイル名.svg}}テンプレートと置き換えてください。

Observer パターン(オブザーバー・パターン)とは、プログラム内のオブジェクトに関するイベント(事象)を他のオブジェクトへ通知する処理で使われるデザインパターンの一種。

通知するオブジェクト側が、通知されるオブジェクト側に観測・観察(: observe)される形になることから、こう呼ばれる。

出版-購読型モデルとも呼ばれる。暗黙的呼び出しの原則と関係が深い。

分散イベント処理システムの実装にも使われる。言語によっては、このパターンで扱われる問題は言語が持つイベント処理構文で処理される。
クラス図

このパターンの基本は、イベントを通知される側の1つ以上のオブジェクト(オブザーバーまたはリスナーと呼ぶ)を、通知する側のオブジェクト(サブジェクトと呼ぶ)に登録することである。そして通知に使われるメソッドが、抽象メソッドになっていることが重要である。言語によっては、コールバック関数と通知対象コンテキストのペア、あるいはそれらをカプセル化した関数オブジェクト、またはデリゲートが使われる[1]

以下に、その構造をUMLクラス図で視覚化したものを示す。


各クラスの解説

このパターンに登場する各インタフェースとインタフェースの実装クラスを、以下で解説する。
Subject

イベントを通知するオブジェクト側のインタフェース。1つ以上のObserverすなわちイベントを通知されるオブジェクト側のインタフェースの登録・削除・通知のメソッド書式の体裁を提供する。

以下の抽象メソッドを持つ:

addObserver() - Subjectが持つ「通知を受け取るObserver群」に、新たなObserverを加える
[注釈 1]

removeObserver() - addObserver()で追加されたオブジェクトを削除する[注釈 2]

notifyObservers() - Subjectが持つ「通知を受け取るObserver群」に、Observer.notify() を呼んでイベントを通知する。

上のUMLクラス図では、Subjectがインタフェースと実装クラスに分かれているが、パターン要件ではない。インタフェースを使わずクラスを直接実装することもある。
ConcreteSubject

Subjectの実装クラス。通知対象であるObserver群を持つ。各Observerが受け取る通知に関する処理を司る。notifyObservers() を呼ぶと、Observer群の1つ以上にイベントを通知する。
Observer

イベントを通知される側のインタフェース。以下の抽象メソッドを持つ:

notify() - Observerにとっては通知を受け取る処理、このメソッドを呼ぶSubjectにとっては通知を送る処理、と言える。このメソッドの個数や各書式は、通知内容により様々である。

ConcreteObserver

Observerの実装クラス。
典型的用法

ユーザーが何らかの操作をするなどの外部イベントを待つ。
イベント駆動型プログラミングを参照。

あるオブジェクトの属性値の変化を待つ。なお、複数の属性値の変化でコールバック関数を呼び出すようにしているとイベントの連鎖的発生を引き起こす。

メーリングリストで、何らかのイベント(新製品情報など)があったとき、購読者リストに登録している人にメッセージを送る。

Observer パターンは Model View Controller (MVC) パラダイムの実装に使われることも多い。MVC では、モデルとビューの連携に Observer パターンが使われる。通常、コントローラーがモデルの変化を検出し、ビュー(オブザーバー)に通知する。
コード例
Python

以下のコードは Python 3.x で Observer パターンを記述したものである。引数を1つ受け取るupdate()メソッドを持つオブジェクトであれば、リスナーとして何でも受け付ける(ダック・タイピング)。なお、例ではリスナーの集合を保持するためにリストを使用しているため、同じオブジェクトの多重登録を許可する実装となっている。class Listener: def __init__(self, name): self.name = name def update(self, event): print(self.name, "received event", event)class Subject: def __init__(self): self.listeners = [] def add_listener(self, listener): self.listeners.append(listener) def remove_listener(self, listener): self.listeners.remove(listener) def notify_listeners(self, event): for listener in self.listeners: listener.update(event)subject = Subject()listenerA = Listener("<listener A>")subject.add_listener(listenerA)listenerB = Listener("<listener B>")subject.add_listener(listenerB)# subject には2つのリスナーが登録されている。subject.notify_listeners("<event 1>")

出力:<listener A> received event <event 1><listener B> received event <event 1>
Java

ロックを避けるため、CopyOnWriteArraySetを使用する例を示す。スレッドセーフにする必要がない、あるいはsynchronizedで同期するのであれば、HashSetやTreeSetを使ってもかまわないが、コンテナの実装によっては順序が保証されず、リスナーを追加したときの順番でupdate()が呼ばれるとは限らない。// Listener.javapublic interface Listener { public void update(String event);}// Subject.javaimport java.util.concurrent.CopyOnWriteArraySet;import java.util.Set;public class Subject { private final Set<Listener> listenerSet = new CopyOnWriteArraySet<Listener>(); public void addListener(Listener listener) { listenerSet.add(listener); } public void removeListener(Listener listener) { listenerSet.remove(listener); } public void notifyListeners(String event) { for (Listener listener : listenerSet) { listener.update(event); } }}// Main.javaclass ListenerImpl implements Listener { private final String name; public ListenerImpl(String name) { this.name = name; } @Override public void update(String event) { System.out.println(this.name + " received event " + event); }}public class Main { public static void main(String[] args) throws Exception { Subject subject = new Subject(); Listener listenerA = new ListenerImpl("<listener A>"); subject.addListener(listenerA); Listener listenerB = new ListenerImpl("<listener B>"); subject.addListener(listenerB); subject.notifyListeners("<event 1>"); }}

出力結果はPythonの例と同じである。
実装

この節に雑多な内容が羅列されています。事項を箇条書きで列挙しただけの節は、本文として組み入れるか、または整理・除去する必要があります。(2021年8月)

ウィキペディアはオンライン百科事典であって、情報を無差別に収集する場ではありません。改善やノートページでの議論にご協力ください。(2021年8月)

Observer パターンは各種ライブラリやシステムに実装されている。特にGUIツールキットには必ず含まれる。


次ページ
記事の検索
おまかせリスト
▼オプションを表示
ブックマーク登録
mixiチェック!
Twitterに投稿
オプション/リンク一覧
話題のニュース
列車運行情報
暇つぶしWikipedia

Size:26 KB
出典: フリー百科事典『ウィキペディア(Wikipedia)
担当:undef