「Observer パターン」の版間の差分
51行目: | 51行目: | ||
以下の[[擬似コード]]は [[Python]] 風文法で Observer パターンを記述したものである。 |
以下の[[擬似コード]]は [[Python]] 風文法で Observer パターンを記述したものである。 |
||
< |
<syntaxhighlight lang="python"> |
||
class Listener: |
class Listener: |
||
def __init__(self, name, subject): |
def __init__(self, name, subject): |
||
82行目: | 82行目: | ||
# <listener A> received event <event 1> |
# <listener A> received event <event 1> |
||
# <listener B> received event <event 1> |
# <listener B> received event <event 1> |
||
</syntaxhighlight> |
|||
</source> |
|||
=== Java === |
=== Java === |
||
ロックを避けるため、CopyOnWriteArraySetを使用する。 |
ロックを避けるため、CopyOnWriteArraySetを使用する。 |
||
< |
<syntaxhighlight lang="java"> |
||
public interface Listener { |
public interface Listener { |
||
public void onEvent(); |
public void onEvent(); |
||
107行目: | 107行目: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
== 実装 == |
== 実装 == |
2020年7月5日 (日) 22:52時点における版
Observer パターン(オブザーバ・パターン)とは、プログラム内のオブジェクトのイベント( 事象 )を他のオブジェクトへ通知する処理で使われるデザインパターンの一種。
通知するオブジェクト側が、通知されるオブジェクト側に観察(英: observe)される形になる事から、こう呼ばれる。
出版-購読型モデルとも呼ばれる。暗黙的呼び出しの原則と関係が深い。
分散イベント処理システムの実装にも使われる。言語によっては、このパターンで扱われる問題は言語が持つイベント処理構文で処理される。
クラス図
このパターンの基本は、イベントを通知される側の1つ以上のオブジェクト(オブザーバ 又は リスナーと呼ぶ)を、通知する側(サブジェクトと呼ぶ)のオブジェクトに登録する事である。そして通知関数が、抽象メソッドになっている事が重要である。
以下に、その構造をUMLクラス図で視覚化したものを示す。
各クラスの解説
このパターンに登場する各インターフェース・メソッド・インターフェースの実装クラスを、以下で解説する。
Subject
イベントを通知するオブジェクト側のインターフェース。1つ以上のObserver( イベントを通知されるオブジェクト側のインターフェース )の登録・削除・通知の関数書式の体裁を提供する。
以下の抽象メソッドを持つ:
- addObserver - Subjectが持つ「 通知を受け取るObserver群 」に、新たなObserverを加える。
- deleteObserver - 上述で加えられた物を削除する。
- 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 風文法で Observer パターンを記述したものである。
class Listener:
def __init__(self, name, subject):
self.name = name
subject.register(self)
def update(self, event):
print self.name, "received event", event
class Subject:
def __init__(self):
self.listeners = []
def register(self, listener):
self.listeners.append(listener)
def unregister(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)
listenerB = Listener("<listener B>", subject)
# subject には2つのリスナーが登録されている。
subject.notify_listeners ("<event 1>")
# 出力:
# <listener A> received event <event 1>
# <listener B> received event <event 1>
Java
ロックを避けるため、CopyOnWriteArraySetを使用する。
public interface Listener {
public void onEvent();
}
import java.util.concurrent.CopyOnWriteArraySet;
public class Subject {
private Set<Listener> listenerSet = new CopyOnWriteArraySet<Listener>();
public void addListener(Listener listener) {
listenerSet.add(listener);
}
private void notifyListeners() {
for (Listener listener : listenerSet) {
listener.onEvent();
}
}
}
実装
Observer パターンは各種ライブラリやシステムに実装されている。特にGUIツールキットには必ず含まれる。
- Java Swing ライブラリは Observer パターンを多用している。
- Boost.Signals - C++ STL の拡張。signal/slot モデルを提供する。
- Qt - C++ フレームワークの signal/slot モデル。
- libsigc++ - C++ シグナルプログラミング・テンプレートライブラリ
- sigslot - C++ Signal/Slot ライブラリ
- XLObject - テンプレートベースの C++ signal/slot モデル
- GLib - C言語でのオブジェクトと signals/callbacks の実装(他のプログラミング言語用の実装もある)
- Exploring the Observer Design Pattern - C# と Visual Basic .NET による実装。delegates を利用。
- Using the Observer Pattern - REALbasic による実装
- flash.events - ActionScript 3.0 でのパッケージ(ActionScript 2.0 の mx.events パッケージの後継)
- YUI Event utility - カスタムイベントを Observer パターンで実装
- Py-notify - Python 実装