Java设计模式之观察者模式:从入门到架构级实践
一、观察者模式的核心价值
观察者模式(Observer Pattern)是行为型设计模式中的经典之作,它建立了对象间的一对多依赖关系,让多个观察者对象能够自动感知被观察对象的状态变化。这种模式在事件驱动系统、实时数据推送、GUI事件处理等场景中广泛应用,是实现松耦合设计的利器。
核心价值体现:
-
解耦生产者(被观察者)与消费者(观察者)
-
支持动态的观察者注册与注销
-
实现广播通信机制
-
符合开放-封闭原则(对扩展开放,对修改关闭)
二、模式结构深度解析
2.1 核心角色分解
-
Subject(抽象主题)
-
维护观察者列表(List<Observer>)
-
提供观察者的注册(attach)和注销(detach)方法
-
定义通知方法(notifyObservers)
-
-
ConcreteSubject(具体主题)
-
维护具体状态信息
-
状态改变时调用父类的通知方法
-
可提供获取状态的接口
-
-
Observer(抽象观察者)
-
定义更新接口(update方法)
-
-
ConcreteObserver(具体观察者)
-
实现具体的更新逻辑
-
可持有主题引用以获取更多状态信息
-
2.2 两种通知模型对比
模型类型 | 数据传递方式 | 优点 | 缺点 |
---|---|---|---|
推模型 | 主题主动推送详细数据给观察者 | 实时性强,响应快 | 可能传递冗余数据 |
拉模型 | 观察者收到通知后主动拉取数据 | 按需获取,灵活性高 | 增加主题的访问压力 |
三、基础实现代码示例
3.1 自定义实现版本
// 抽象主题
interface Subject {void register(Observer o);void remove(Observer o);void notifyObservers();
}// 具体主题(气象站)
class WeatherStation implements Subject {private List<Observer> observers = new ArrayList<>();private float temperature;public void setMeasurements(float temp) {this.temperature = temp;notifyObservers();}@Overridepublic void register(Observer o) { observers.add(o); }@Overridepublic void remove(Observer o) { observers.remove(o); }@Overridepublic void notifyObservers() {for (Observer o : observers) {o.update(temperature);}}
}// 抽象观察者
interface Observer {void update(float temp);
}// 具体观察者(手机显示)
class PhoneDisplay implements Observer {@Overridepublic void update(float temp) {System.out.println("手机显示温度更新:" + temp + "℃");}
}
3.2 Java内置实现
Java自带的java.util.Observable
类和Observer
接口:
class WeatherData extends Observable {private float temperature;public void measurementsChanged() {setChanged(); // 必须调用此方法notifyObservers();}public void setMeasurements(float temp) {this.temperature = temp;measurementsChanged();}// 供观察者拉取数据public float getTemperature() {return temperature;}
}class TVDisplay implements Observer {@Overridepublic void update(Observable o, Object arg) {if (o instanceof WeatherData) {WeatherData wd = (WeatherData) o;System.out.println("电视显示当前温度:" + wd.getTemperature());}}
}
四、高级架构实践
4.1 异步观察者模式
ExecutorService executor = Executors.newCachedThreadPool();class AsyncNotifier {public void notifyAsync(List<Observer> observers) {observers.forEach(observer -> executor.submit(() -> observer.update()));}
}
注意事项:
-
线程安全性问题
-
通知顺序无法保证
-
异常处理机制
-
资源释放管理
4.2 基于Java Flow的响应式实现
Java 9+ 引入的响应式流API:
class TemperaturePublisher implements Publisher<Float> {private final SubmissionPublisher<Float> publisher = new SubmissionPublisher<>();public void publish(float temp) {publisher.submit(temp);}@Overridepublic void subscribe(Subscriber<? super Float> subscriber) {publisher.subscribe(subscriber);}
}class FlowDisplay implements Subscriber<Float> {private Subscription subscription;@Overridepublic void onSubscribe(Subscription s) {this.subscription = s;s.request(1);}@Overridepublic void onNext(Float temp) {System.out.println("Flow显示温度:" + temp);subscription.request(1);}
}
五、典型应用场景
5.1 电商订单系统
class OrderService {private List<OrderObserver> observers = new CopyOnWriteArrayList<>();public void placeOrder(Order order) {// 创建订单逻辑...notifyObservers(order);}private void notifyObservers(Order order) {observers.forEach(observer -> {try {observer.onOrderCreated(order);} catch (Exception e) {// 异常处理}});}
}interface OrderObserver {void onOrderCreated(Order order);
}// 库存扣减观察者
class InventoryObserver implements OrderObserver {@Overridepublic void onOrderCreated(Order order) {inventoryService.reduceStock(order.getItems());}
}
5.2 微服务配置中心
@RestController
public class ConfigController {private final ConfigSubject configSubject;@PostMapping("/update-config")public void updateConfig(@RequestBody Config newConfig) {configSubject.updateConfig(newConfig);}
}@Service
class ConfigSubject {private List<ConfigObserver> observers = new ArrayList<>();private Config currentConfig;public synchronized void updateConfig(Config newConfig) {this.currentConfig = newConfig;notifyObservers();}private void notifyObservers() {observers.forEach(observer -> observer.onConfigChanged(currentConfig));}
}
六、生产环境最佳实践
-
性能优化策略
-
采用CopyOnWriteArrayList避免并发修改异常
-
使用Guava的EventBus进行事件分发
-
实现观察者优先级机制
-
添加批处理通知功能
-
-
可靠性增强
-
引入死信队列处理失败通知
-
实现幂等性处理
-
添加事务消息支持
-
建立监控指标体系(QPS、失败率等)
-
-
扩展性设计
-
支持观察者过滤器
-
实现主题分组机制
-
添加消息持久化能力
-
支持跨进程观察(分布式观察者)
-
七、常见陷阱与解决方案
典型问题1:内存泄漏
-
现象:观察者未及时注销导致无法回收
-
解决方案:
// 使用弱引用 class WeakObserver implements Observer {WeakReference<Observer> ref;public WeakObserver(Observer real) {this.ref = new WeakReference<>(real);}// 实现代理方法... }
典型问题2:循环通知
-
现象:A通知B,B又通知A导致死循环
-
解决方案:
class SafeSubject implements Subject {private boolean notifying = false;public void notifyObservers() {if (notifying) return;notifying = true;try {// 执行通知...} finally {notifying = false;}} }
典型问题3:性能瓶颈
-
现象:同步通知大量观察者导致响应延迟
-
解决方案:
// 分片异步通知 List<List<Observer>> shards = partition(observers, 10); shards.forEach(shard -> executor.execute(() -> shard.forEach(Observer::update)) );
八、模式演进与变种
-
中介者模式结合
-
通过中介者统一管理观察关系
-
实现更复杂的消息路由
-
-
响应式扩展
-
结合RxJava实现流式处理
-
支持背压(Backpressure)机制
-
-
领域事件模式
-
在DDD中应用观察者模式
-
实现领域事件的发布/订阅
-
-
CQRS架构集成
-
将命令与查询分离
-
通过观察者维护读模型
-
九、总结与展望
观察者模式作为解耦利器,在现代架构中展现出强大的生命力。随着响应式编程的兴起,观察者模式正在与以下新技术深度融合:
-
云原生架构:跨服务的观察者模式实现
-
Serverless:事件驱动的函数计算
-
物联网(IoT):海量设备的状态同步
-
实时数据分析:流式计算中的事件处理
建议开发者根据具体场景选择合适的实现方式:
-
简单场景:直接使用语言内置支持
-
复杂系统:采用成熟的响应式框架(如RxJava、Reactor)
-
分布式环境:使用消息中间件(如Kafka、RabbitMQ)
掌握观察者模式的精髓,将使你的系统架构具备更好的扩展性和灵活性,从容应对各种复杂的业务需求变化。