📢 この記事は gemini-3-flash-preview によって翻訳されました
Observer Pattern (オブザーバーパターン) オブジェクト振る舞い型パターン
意図
オブジェクト間に一対多の依存関係を定義して、あるオブジェクトの状態が変化したときに、それに依存しているすべてのオブジェクトに通知が届き、自動的に更新されるようにすること。
構造

役割:
- Subject (目標): 自分のオブザーバー(観察者)を知っている。任意の数のオブザーバーが一つの目標を観察できる。オブザーバーを登録したり削除したりするためのインターフェースを提供するよ。
- Observer (オブザーバー): 目標に変化があったときに通知を受け取る必要があるオブジェクトのために、更新用のインターフェースを定義する。
- ConcreteSubject (具体的な目標): 関連する状態を各 ConcreteObserver オブジェクトに保存する。自分の状態が変化したときに、登録されているオブザーバーたちに通知を送るんだ。
- ConcreteObserver (具体的なオブザーバー): ConcreteSubject オブジェクトへの参照を保持する。目標の状態と一致させておくべき状態を保存する。Observer の更新インターフェースを実装して、自分の状態を目標の状態に合わせるよ。
適用場面
Observer パターンはこんな時に使えるよ:
- 抽象的なモデルに2つの側面があって、片方がもう片方に依存している場合。これらを独立したオブジェクトにカプセル化することで、それぞれをバラバラに変更したり再利用したりできるようになる。
- 1つのオブジェクトを変更したときに、他のオブジェクトも同時に変更する必要があるけれど、具体的にいくつのオブジェクトを変更しなきゃいけないか分からないとき。
- あるオブジェクトが他のオブジェクトに通知を送る必要があるけれど、その相手が誰かを特定したくない(つまり、ガチガチに結合させたくない)とき。
例 1
あるファイル管理システムで OfficeDoc クラスと DocExplorer クラスが定義されているとする。OfficeDoc クラスに変化があったとき、DocExplorer クラスのすべてのオブジェクトが自分の状態を更新しなきゃいけない。これをオブザーバーパターンを使って実現すると、クラス図は以下のようになるよ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
| import java.util.*;
interface Observer {
public void update();
}
interface Subject {
public void Attach(Observer obs);
public void Detach(Observer obs);
public void Notify();
public void setStatus(int status);
public int getStatus();
}
class OfficeDoc implements Subject {
private List<Observer> myObs;
private String mySubjectName;
private int m_status;
public OfficeDoc(String name) {
mySubjectName = name;
this.myObs = new ArrayList<Observer>();
m_status = 0;
}
public void Attach(Observer obs) { this.myObs.add(obs); }
public void Detach(Observer obs) { this.myObs.remove(obs); }
public void Notify() {
for (Observer obs : this.myObs) {obs.update(); }
}
public void setStatus(int status) {
m_status = status;
System.out.println("SetStatus subject[" + mySubjectName + "]status:" + status);
}
public int getStatus() { return m_status; }
}
class DocExplorer implements Observer {
private String myObsName;
public DocExplorer(String name,Subject sub) {
myObsName = name;
sub.Attach(this);
}
public void update() {
System.out.println("update observer[" + myObsName + "]");
}
}
class ObserverTest {
public static void main(String[] args) {
Subject subjectA = new OfficeDoc("subject A");
Observer observerA = new DocExplorer("observer A", subjectA);
subjectA.setStatus(1);
subjectA.Notify();
}
}
|
例 2
Subject を YouTuber、Observer をチャンネル登録者とする例だよ。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
| import java.util.ArrayList;
import java.util.List;
public class ObserverPattern {
public static void main(String[] args) {
Subject subjectA = new ConcerteSubject();
Observer observer1 = new ConcerteObserver("Mike", subjectA);
Observer observer2 = new ConcerteObserver("Jane", subjectA);
subjectA.Notify();
}
}
interface Subject{ // 目標
public void Attach(Observer observer);
public void Detach(Observer observer);
public void Notify();
public String getState();
public void setState(String state);
}
class ConcerteSubject implements Subject{
private String state;
private List<Observer> observerList;
public String getState() {
return state;
}
@Override
public void setState(String state) {
this.state = state;
this.Notify();
}
public ConcerteSubject(){
state = "-1";
observerList = new ArrayList<>();
}
public void Attach(Observer observer){
observerList.add(observer);
}
public void Detach(Observer observer){
observerList.remove(observer);
}
public void Notify(){
for(Observer o : observerList){
o.update();
}
}
}
interface Observer{ // オブザーバー
public void update();
}
class ConcerteObserver implements Observer{
private String name;
private Subject subject;
private String state;
public ConcerteObserver(String name, Subject subject){
this.name = name;
this.state = subject.getState();
this.subject = subject;
subject.Attach(this);
}
@Override
public void update(){
System.out.println(this.name + " Received");
this.state = subject.getState();
}
}
|