设计模式|观察者模式

观察者模式也是比较常用的一个模式,常常用于,当一个对象的状态发生改变时,对于所有”订阅“了这个对象的对象,需要做出对应的行为。但是这些对象往往需要在运行过程中才会被确定

这个场景我们就可以使用观察者模式

例如商品库存的例子,商品库存不够时,需要通知其他订阅了商品库存数量的服务

代码最佳实践

被观察者接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface Subject {
// 添加观察者
void addObserver(Observer observer);

// 移除观察者
void removeObserver(Observer observer);

// 通知所有观察者
void notifyObservers();


String getName();

int getStock();

}

被观察者实现类

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
// 商品类(具体被观察者)
public class Product implements Subject {
private String id;
private String name;
private int stock; // 库存数量
private List<Observer> observers = new ArrayList<>();

public Product(String id, String name, int stock) {
this.id = id;
this.name = name;
this.stock = stock;
}

// 减少库存
public void reduceStock(int quantity) {
if (quantity > 0 && quantity <= stock) {
stock -= quantity;
System.out.println(name + " 减少库存 " + quantity + ",当前库存:" + stock);

// 当库存低于阈值时,通知观察者
if (stock <= 5) {
notifyObservers();
}
}
}

// 添加库存
public void addStock(int quantity) {
if (quantity > 0) {
stock += quantity;
System.out.println(name + " 增加库存 " + quantity + ",当前库存:" + stock);
}
}

// getter方法
public String getId() { return id; }
public String getName() { return name; }
public int getStock() { return stock; }

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

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

@Override
public void notifyObservers() {
System.out.println("=== 库存不足,开始通知相关方 ===");
for (Observer observer : observers) {
observer.update(this);
}
}
}

观察者接口

1
2
3
4
public interface Observer {
// 接收通知的方法
void update(Subject subject);
}

观察者实现类

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
// 前端观察者(收到通知后显示缺货标识)
public class FrontendObserver implements Observer {
@Override
public void update(Subject subject) {
System.out.println("前端收到通知:" + subject.getName() + " 库存不足");
System.out.println("前端操作:已显示'库存紧张'标识");
}
}

// 用户观察者(收到通知后提醒用户)
public class UserObserver implements Observer {
private String username;

public UserObserver(String username) {
this.username = username;
}

@Override
public void update(Subject subject) {
System.out.println("用户 " + username + " 收到通知:您关注的 " + subject.getName() + " 库存不足(当前:" + subject.getStock() + ")");
System.out.println("用户通知:建议尽快购买");
}
}

// 仓库观察者(收到通知后补充库存)
public class WarehouseObserver implements Observer {
@Override
public void update(Subject subject) {
System.out.println("仓库收到通知:" + subject.getName() + " 库存不足(当前:" + subject.getStock() + ")");
System.out.println("仓库操作:已安排补货,预计24小时内到货");
}
}

核心设计

观察者模式的核心设计在于,被观察者会在程序运行时,持有所有观察者的引用(商品持有所有的观察者List)

一旦触发某些状态变动后(商品库存更新)

被观察者调用观察者的指定逻辑(商品调用观察者的update方法)

实践应用

Spring中的事件就是基于观察者模式的扩展

主要有三个角色

观察者模式角色 Spring 组件 作用说明
被观察者(Subject) ApplicationEventPublisher 负责发布事件(通知观察者),Spring 容器(ApplicationContext)默认实现该接口
观察者(Observer) ApplicationListener<T> 泛型接口,T是具体事件类型,实现onApplicationEvent(T event)方法接收通知
也可以通过在Spring bean中的某个方法上标记@EventListener注解来替换这个 onApplicationEvent实现
通知数据 ApplicationEvent 事件基类,自定义事件需继承它,用于传递通知时的业务数据

设计模式|观察者模式
http://example.com/2025/08/27/设计模式-观察者模式/
作者
Noctis64
发布于
2025年8月27日
许可协议