Observer パターン
Observer パターン(オブザーバー・パターン)とは、プログラム内のオブジェクトに関するイベント(事象)を他のオブジェクトへ通知する処理で使われるデザインパターンの一種。 通知するオブジェクト側が、通知されるオブジェクト側に観測・観察(英: observe)される形になることから、こう呼ばれる。 出版-購読型モデルとも呼ばれる。暗黙的呼び出しの原則と関係が深い。 分散イベント処理システムの実装にも使われる。言語によっては、このパターンで扱われる問題は言語が持つイベント処理構文で処理される。 クラス図このパターンの基本は、イベントを通知される側の1つ以上のオブジェクト(オブザーバーまたはリスナーと呼ぶ)を、通知する側のオブジェクト(サブジェクトと呼ぶ)に登録することである。そして通知に使われるメソッドが、抽象メソッドになっていることが重要である。言語によっては、コールバック関数と通知対象コンテキストのペア、あるいはそれらをカプセル化した関数オブジェクト、またはデリゲートが使われる[1]。 以下に、その構造をUMLクラス図で視覚化したものを示す。 各クラスの解説このパターンに登場する各インタフェースとインタフェースの実装クラスを、以下で解説する。 Subjectイベントを通知するオブジェクト側のインタフェース。1つ以上のObserverすなわちイベントを通知されるオブジェクト側のインタフェースの登録・削除・通知のメソッド書式の体裁を提供する。 以下の抽象メソッドを持つ:
上のUMLクラス図では、Subjectがインタフェースと実装クラスに分かれているが、パターン要件ではない。インタフェースを使わずクラスを直接実装することもある。 ConcreteSubjectSubjectの実装クラス。通知対象であるObserver群を持つ。各Observerが受け取る通知に関する処理を司る。notifyObservers() を呼ぶと、Observer群の1つ以上にイベントを通知する。 Observerイベントを通知される側のインタフェース。以下の抽象メソッドを持つ:
ConcreteObserverObserverの実装クラス。 典型的用法
Observer パターンは Model View Controller (MVC) パラダイムの実装に使われることも多い。MVC では、モデルとビューの連携に Observer パターンが使われる。通常、コントローラーがモデルの変化を検出し、ビュー(オブザーバー)に通知する。 コード例Python以下のコードは Python 3.x で Observer パターンを記述したものである。引数を1つ受け取る 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ロックを避けるため、 // Listener.java
public interface Listener {
public void update(String event);
}
// Subject.java
import 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.java
class 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の例と同じである。 実装
Observer パターンは各種ライブラリやシステムに実装されている。特にGUIツールキットには必ず含まれる。
脚注注釈出典関連項目外部リンク
|
Portal di Ensiklopedia Dunia