设计模式-观察者模式
观察者模式
问题
1 | 气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方)。 |
基本原理
观察者模式类似订牛奶业务1
奶站/气象局:Subject
用户/第三方网站:Observer
Subject:登记注册、移除和通知

- 抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
- 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
- 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
- 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
解决问题
接口,主题
1
2
3
4
5public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}观察者接口
1
2
3public interface Observer {
public void update(Data data);
}具体主题,具体主题天气信息包含一个天气数据,和观察者列表,当数据发生变化是通知观察者。
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
35public class Data {
private float temperature;
private float pressure;
private float humidity;
public Data(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
}
public float getTemperature() {
return temperature;
}
public void setTemperature(float temperature) {
this.temperature = temperature;
}
public float getPressure() {
return pressure;
}
public void setPressure(float pressure) {
this.pressure = pressure;
}
public float getHumidity() {
return humidity;
}
public void setHumidity(float humidity) {
this.humidity = humidity;
}
}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
42public class WeatherData implements Subject{
//观察者集合
private ArrayList<Observer> observers;
//数据
private Data data;
public WeatherData(){
observers = new ArrayList<Observer>();
}
//当有新的数据更新时,调用
public void setData(float temperature,float pressure,float humidity){
this.data = new Data(temperature,pressure,humidity);
notifyObserver(); //通知观察者
}
//注册观察者
public void registerObserver(Observer o) {
observers.add(o);
}
//移除观察者
public void removeObserver(Observer o) {
if (observers.contains(o)) {
observers.remove(o);
}
}
/**
* 通知观察者
*/
public void notifyObserver() {
for (int i = 0; i <observers.size(); i++){
observers.get(i).update(data);
}
}
}观察者,数据发生变化时进行update操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class CurrentConditions implements Observer{
//温度,气压,湿度
private Data data;
public void update(Data data) {
this.data = data;
display();
}
public void display(){
System.out.println("temperature:"+data.getTemperature());
System.out.println("pressure:"+data.getPressure());
System.out.println("humidity:"+data.getHumidity());
}
}客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class Client {
public static void main(String[] args) {
//创建一个主题
WeatherData weatherData = new WeatherData();
//创建观察者
CurrentConditions currentConditions = new CurrentConditions();
//注册到weatherData
weatherData.registerObserver(currentConditions);
//测试
weatherData.setData(10, 100, 30);
}
}
观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册,移除和通知。
这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核心类WeatherData不会修改代码,遵守了ocp原则。
源码分析
Observable源码
1 | public class Observable { |
JDK的Observable对象中使用Vector存放观察者对象。观察者接口如下:
1 | public interface Observer { |