Observer パターン
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2023/02/26 16:46 UTC 版)
コード例
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.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 パターンのページへのリンク