1. 观察者模式概述
概述
- 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
Demo
观察者的接口
1
2
3public interface Observer {
void update(String event);
}被观察者的父类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class Observable {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String event) {
for (Observer observer : observers) {
observer.update(event);
}
}
}警察属于观察者
1
2
3
4
5
6public class PoliceObserver implements Observer {
@Override
public void update(String event) {
System.out.println("警察收到消息,罪犯在" + event);
}
}罪犯属于被观察者
1
2
3
4
5
6public class CriminalObservable extends Observable {
public void crime(String event) {
System.out.println("罪犯正在" + event);
notifyObservers(event);
}
}客户端测试
1
2
3
4
5
6
7
8
9
10
11
12
13public class Client {
@Test
public void test() {
CriminalObservable zhangSan = new CriminalObservable();
PoliceObserver police1 = new PoliceObserver();
PoliceObserver police2 = new PoliceObserver();
PoliceObserver police3 = new PoliceObserver();
zhangSan.addObserver(police1);
zhangSan.addObserver(police2);
zhangSan.addObserver(police3);
zhangSan.crime("放狗咬人");
}
}
2. Java 源码中的观察者模式
java.util.Observer 类
1
2
3public interface Observer {
void update(Observable o, Object arg);
}update()
方法将 Observable 对象也提供给了 Observerupdate()
方法中的参数类型变成了 Object,保证 Observer 的适用范围更广
java.util.Observable 类
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
56public class Observable {
private boolean changed = false;
private Vector<Observer> obs;
public Observable() {
obs = new Vector<>();
}
public synchronized void addObserver(java.util.Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
public synchronized void deleteObserver(java.util.Observer o) {
obs.removeElement(o);
}
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!hasChanged())
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length - 1; i >= 0; i--)
((Observer) arrLocal[i]).update(this, arg);
}
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return obs.size();
}
}- 用于保存观察者列表的容器不是 ArrayList,而是 Vetor
- 添加了一个 changed 字段,以及
setChanged()
方法和clearChanged()
方法。分析可知,当 changed 字段为 true 时,才会通知所有观察者,否则不通知观察者。所以当使用此类时,想要触发notifyObservers()
方法,必须先调用setChanged()
方法。这个字段相当于在被观察者和观察者之间添加了一个可控制的阀门 - 提供了 countObservers 方法,用于计算观察者数量
- 添加了一些 synchronized 关键字保证线程安全
3. 观察者模式练习题(多选)
在电影《让子弹飞》中,马县长、县长夫人和康师爷一起吃着火锅,唱着歌,突然被马匪张麻子给劫了!这个过程中体现了哪些观察者模式?
- 马县长观察着火锅
- 张麻子观察着县长车队
- 县长夫人观察着窗外风景
- 康师爷观察着县长夫人
题目解析
马县长观察着火锅,当火锅烫好后吃肉;张麻子观察着县长车队,趁县长车队路过时打劫。3 和 4 都只是凝视,不会因为被观察者的变化而做出任何响应,属于 watch 、不属于 observe