Java设计模式之观察者模式

Java设计模式之观察者模式

观察者模式

观察者模式(Observer Pattern)是一种行为设计模式,定义了对象之间一对多的依赖关系,当一个对象状态发生改变时,所有依赖它的对象都会收到通知并自动更新。这种模式常用于实现分布式事件处理系统。

模式概述

观察者模式也被称为发布-订阅(Publish-Subscribe)模式。在该模式中:

  • 主题(Subject):被观察的对象,维护一组观察者,提供添加、删除和通知观察者的方法
  • 观察者(Observer):监听主题变化的对象,当收到通知时执行相应的更新操作

观察者模式的结构

角色组成

  1. Subject(抽象主题):定义主题的接口,包括注册、注销和通知观察者的方法
  2. ConcreteSubject(具体主题):实现抽象主题接口,维护观察者列表,当状态改变时通知所有观察者
  3. Observer(抽象观察者):定义观察者的接口,包含更新方法
  4. ConcreteObserver(具体观察者):实现抽象观察者接口,在收到通知时执行具体的更新逻辑

UML结构图

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
        ┌─────────────────┐
│ Subject │
│ (抽象主题) │
├─────────────────┤
│ + register() │
│ + unregister() │
│ + notifyAll() │
└────────┬────────┘
│ 继承

┌─────────────────┐
│ ConcreteSubject │
│ (具体主题) │
├─────────────────┤
│ - observers[] │
│ - state │
└────────┬────────┘
│ 通知
┌────────┼────────┬────────┐
▼ ▼ ▼ ▼
┌───────────┐┌───────────┐┌───────────┐┌───────────┐
│ Observer ││ Observer ││ Observer ││ Observer │
│ (观察者) ││ (观察者) ││ (观察者) ││ (观察者) │
├───────────┤├───────────┤├───────────┤├───────────┤
│ + update()││ + update()││ + update()││ + update()│
└───────────┘└───────────┘└───────────┘└───────────┘

观察者模式的实现

基础实现

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
101
// 抽象观察者接口
public interface Observer {
void update(String message);
}

// 抽象主题接口
public interface Subject {
void registerObserver(Observer observer);
void unregisterObserver(Observer observer);
void notifyObservers();
}

// 具体主题
public class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private String state;

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
notifyObservers(); // 状态改变时通知所有观察者
}

@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}

@Override
public void unregisterObserver(Observer observer) {
observers.remove(observer);
}

@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
}

// 具体观察者A
public class ConcreteObserverA implements Observer {
private String name;

public ConcreteObserverA(String name) {
this.name = name;
}

@Override
public void update(String message) {
System.out.println(name + " 收到消息: " + message);
}
}

// 具体观察者B
public class ConcreteObserverB implements Observer {
private String name;

public ConcreteObserverB(String name) {
this.name = name;
}

@Override
public void update(String message) {
System.out.println(name + " 处理消息: " + message);
}
}

// 测试类
public class ObserverPatternTest {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();

Observer observerA = new ConcreteObserverA("观察者A");
Observer observerB = new ConcreteObserverB("观察者B");

// 注册观察者
subject.registerObserver(observerA);
subject.registerObserver(observerB);

// 改变状态,触发通知
subject.setState("Hello World!");
System.out.println("-------------------");

// 注销观察者A
subject.unregisterObserver(observerA);

// 再次改变状态
subject.setState("Hello Observer!");
}
/**Output
* 观察者A 收到消息: Hello World!
* 观察者B 处理消息: Hello World!
* -------------------
* 观察者B 处理消息: Hello Observer!
*///~
}

Java内置观察者模式

Java提供了内置的观察者模式实现:java.util.Observablejava.util.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
import java.util.Observable;
import java.util.Observer;

// 具体主题,继承Observable
public class WeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure;

public void measurementsChanged() {
setChanged(); // 标记状态已改变
notifyObservers(); // 通知所有观察者
}

public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}

public float getTemperature() {
return temperature;
}

public float getHumidity() {
return humidity;
}

public float getPressure() {
return pressure;
}
}

// 具体观察者
public class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;

public CurrentConditionsDisplay(Observable observable) {
observable.addObserver(this);
}

@Override
public void update(Observable obs, Object arg) {
if (obs instanceof WeatherData) {
WeatherData weatherData = (WeatherData) obs;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}

public void display() {
System.out.println("当前温度: " + temperature + "°C, 湿度: " + humidity + "%");
}
}

// 测试类
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay display = new CurrentConditionsDisplay(weatherData);

weatherData.setMeasurements(25.5f, 60f, 1013.25f);
weatherData.setMeasurements(26.0f, 65f, 1012.75f);
}
/**Output
* 当前温度: 25.5°C, 湿度: 60.0%
* 当前温度: 26.0°C, 湿度: 65.0%
*///~
}

观察者模式的优缺点

优点

  1. 松耦合:主题和观察者之间是松耦合的,彼此不知道对方的具体实现
  2. 可扩展性:可以随时添加或删除观察者,符合开闭原则
  3. 广播通信:主题状态改变时,所有观察者都会收到通知
  4. 职责分离:主题负责维护状态,观察者负责处理更新逻辑

缺点

  1. 内存泄漏风险:如果观察者注册后没有正确注销,可能导致内存泄漏
  2. 通知顺序问题:观察者收到通知的顺序不确定
  3. 性能问题:如果观察者数量过多,通知过程可能会影响性能

观察者模式的应用场景

  1. GUI事件处理:按钮点击、键盘输入等事件的处理
  2. 消息队列系统:生产者-消费者模式
  3. 分布式系统:服务间的事件通知
  4. 数据绑定:UI组件与数据源的双向绑定
  5. 日志系统:多个日志处理器监听日志事件

总结

观察者模式是一种非常实用的设计模式,它实现了对象之间的解耦,使得主题和观察者可以独立变化。在实际开发中,我们可以使用Java内置的ObservableObserver,也可以根据需求自定义实现。

使用观察者模式时需要注意:

  • 及时注销不再需要的观察者,避免内存泄漏
  • 考虑通知的顺序是否会影响业务逻辑
  • 对于性能敏感的场景,可以考虑异步通知或批量通知

参考资料

发布于

2018-11-15

更新于

2026-05-22

许可协议

评论

:D 一言句子获取中...

加载中,最新评论有1分钟缓存...