观察者模式也是比较常用的一个模式,常常用于,当一个对象的状态发生改变时,对于所有”订阅“了这个对象的对象,需要做出对应的行为。但是这些对象往往需要在运行过程中才会被确定
这个场景我们就可以使用观察者模式
例如商品库存的例子,商品库存不够时,需要通知其他订阅了商品库存数量的服务
代码最佳实践
被观察者接口
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); } } 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 |
事件基类,自定义事件需继承它,用于传递通知时的业务数据 |