观察者模式
观察者模式又叫发布订阅模式,通常用在事件监听和数据变更通知场景中。当一个对象状态发生改变时,所有依赖于它的对象都会得到变更通知,时一种对象间一对多关系。
案例:当天气发生变化时,电视台播放天气预告,手机推送天气消息。
# 不使用第三方类库实现
public interface Subject<M> {
/**
* 添加监听者
*/
void register(Observer<M> observer);
/**
* 移除监听者
*/
void unregister(Observer<M> observer);
void notifyObservers();
/**
* 事件通知
*/
void notifyObservers(M msg);
}
// 通用 Subject 封装
public class Observable<M> implements Subject<M> {
/**
* executor != null 时,异步通知
*/
private final Executor executor;
private final List<Observer<M>> observers;
public Observable() {
this.executor = null;
this.observers = new CopyOnWriteArrayList<>();
}
public Observable(final Executor executor) {
this.executor = executor;
this.observers = new CopyOnWriteArrayList<>();
}
@Override
public void register(final Observer<M> observer) {
observers.add(observer);
}
@Override
public void unregister(final Observer<M> observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
this.notifyObservers(null);
}
@Override
public void notifyObservers(M msg) {
if (executor == null) {
observers.forEach(item -> item.update(msg));
return;
}
observers.forEach(item -> executor.execute(() -> item.update(msg)));
}
}
// 具体 Subject 实现
public class Weather extends Observable<WeatherType> {
private static final AtomicInteger curr = new AtomicInteger(0);
public void weatherChange() {
final WeatherType[] weatherTypes = WeatherType.values();
WeatherType currentWeather = weatherTypes[curr.getAndIncrement() % weatherTypes.length];
System.out.println("天气发生变化:" + currentWeather);
notifyObservers(currentWeather);
}
}
// 观察者
public interface Observer<M> {
void update(M msg);
}
public class TvWeatherObserver implements Observer<WeatherType> {
@Override
public void update(final WeatherType msg) {
System.out.println("电视台天气预告,当前天气:" + msg.getDescription());
}
}
public class PhoneWeatherObserver implements Observer<WeatherType> {
@Override
public void update(final WeatherType msg) {
System.out.println("手机推送,当前天气:" + msg.getDescription());
}
}
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
测试类
public class WeatherApp {
public static void main(String[] args) {
Weather weather = new Weather();
weather.register(new TvWeatherObserver());
weather.register(new PhoneWeatherObserver());
weather.weatherChange();
weather.weatherChange();
weather.weatherChange();
weather.weatherChange();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 使用guava
实现
public class GuavaWeather {
private final EventBus bus = new EventBus("weather");
private static final AtomicInteger curr = new AtomicInteger(0);
public void register(final Object observer) {
bus.register(observer);
}
public void unregister(final Object observer) {
bus.unregister(observer);
}
public void weatherChange() {
final WeatherType[] weatherTypes = WeatherType.values();
WeatherType currentWeather = weatherTypes[curr.getAndIncrement() % weatherTypes.length];
System.out.println("天气发生变化:" + currentWeather);
bus.post(currentWeather);
}
}
public class GuavaTvWeatherObserver {
@Subscribe
public void update(final WeatherType msg) {
System.out.println("电视台天气预告,当前天气:" + msg.getDescription());
}
}
public class GuavaPhoneWeatherObserver {
@Subscribe
public void update(WeatherType msg) {
System.out.println("手机推送,当前天气:" + msg.getDescription());
}
}
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
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
测试类
public class GuavaWeatherApp {
public static void main(String[] args) {
final GuavaWeather weather = new GuavaWeather();
weather.register(new GuavaTvWeatherObserver());
weather.register(new GuavaPhoneWeatherObserver());
weather.weatherChange();
weather.weatherChange();
weather.weatherChange();
weather.weatherChange();
weather.weatherChange();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
EventBus
源码可以查看https://github.com/google/guava/blob/master/guava/src/com/google/common/eventbus/EventBus.java (opens new window)
另外guava
还提供了异步支持AsyncEventBus (opens new window)
Last Updated: 2024/04/23, 01:30:37