观察者模式
Observer Pattern 对象行为型模式
意图
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变吋,所有依赖于它的对象都得到通知并被自动更新
结构
其中:
- Subject (目标) 知道它的观察者,可以有任意多个观察者观察同一个目标;提供注册和删除观察者对象的接口
- Observer (观察者) 为那些在”目标发生改变时需获得通知的对象定义一个更新接口
- ConcreteSubject (具体目标) 将有关状态存入各 ConcreteObserver 对象:当它的状态发生改变时,向它的各个观察者发出通知
- ConcreteObserver (具体观察者) 维护一个指向 ConcreteSubject 对象的引用:存储有关状态,这些状态应与目标的状态保持一致:实现 Observer 的更新接口,以使自身状态与目标的状态保持一致
适用性
Observer 模式适用于:
- 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两者封装在独立的对象中以使它们可以各自独立地改变和复用
- 当对一个对象的改变需要同时改变其他对象,而不知道具休有多少对象有待改变吋
- 当一个对象必须通知其他对象,向它又不能假定其他对象是谁,即不希望这些对象是紧耦合的
例子 1
某文件管理系统中定义了类 OfficeDoc 和 DocExplorer。当类 OfficeDoc 发生变化时,类 DocExplorer 的所有对象都要更新其自身的状态。现采用观察者 (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
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();
}
}