Java设计模式之行为型模式(观察者模式)介绍与说明
一、模式结构
观察者模式包含以下四个角色:
- Subject(主题/被观察者)
- 维护观察者列表,提供注册(
registerObserver
)、移除(removeObserver
)观察者的方法,并定义通知所有观察者的方法(notifyObservers
)。 - 示例:天气数据(
WeatherData
)、优衣库品牌决策(UniqloBrandDecision
)。
- 维护观察者列表,提供注册(
- Observer(观察者)
- 定义更新接口(
update
),用于接收主题的通知并执行响应逻辑。 - 示例:天气显示组件(
CurrentConditionsDisplay
)、消费者(Consumer
)。
- 定义更新接口(
- ConcreteSubject(具体主题)
- 实现主题接口,管理观察者列表,并在状态变化时触发通知。例如,
WeatherData
类在温度、湿度等数据更新时调用notifyObservers
。
- 实现主题接口,管理观察者列表,并在状态变化时触发通知。例如,
- ConcreteObserver(具体观察者)
- 实现观察者接口,定义具体响应逻辑。例如,
CurrentConditionsDisplay
在接收到数据后更新显示内容。
- 实现观察者接口,定义具体响应逻辑。例如,
二、核心实现步骤
- 定义观察者接口:声明
update
方法,参数可为数据对象或主题引用(推模型或拉模型)。 - 实现具体观察者:在
update
方法中处理主题状态变化,例如更新UI或执行业务逻辑。 - 定义主题接口:包含观察者管理方法和通知方法。
- 实现具体主题:维护观察者列表,在状态变化时遍历并调用
update
方法。
三、代码示例(气象站系统)
// 观察者接口
public interface Observer {void update(float temp, float humidity, float pressure);
}
// 主题接口
public interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();
}
// 具体主题类(天气数据)
public class WeatherData implements Subject {private List observers = new ArrayList<>();private float temperature, humidity, pressure;@Overridepublic void registerObserver(Observer o) { observers.add(o); }@Overridepublic void removeObserver(Observer o) { observers.remove(o); }@Overridepublic void notifyObservers() {for (Observer o : observers) {o.update(temperature, humidity, pressure);}}public void measurementsChanged() {notifyObservers();}public void setMeasurements(float temp, float humidity, float pressure) {this.temperature = temp;this.humidity = humidity;this.pressure = pressure;measurementsChanged();}
}
// 具体观察者类(当前天气显示)
public class CurrentConditionsDisplay implements Observer {private float temp, humidity;@Overridepublic void update(float temp, float humidity, float pressure) {this.temp = temp;this.humidity = humidity;display();}private void display() {System.out.println("当前温度:" + temp + "℃,湿度:" + humidity + "%");}
}
四、适用场景
- 事件驱动系统:如GUI事件处理、按钮点击监听。
- 实时数据监控:股票价格变动、传感器数据更新。
- 订阅/发布模型:邮件订阅、RSS订阅、消息队列。
- 跨模块通知:订单状态变更通知多个服务。
五、优缺点分析
优点 | 缺点 |
---|---|
- 解耦主题与观察者,符合开闭原则。 | - 观察者过多时性能下降。 |
- 动态扩展观察者,无需修改核心逻辑。 | - 通知顺序不可控,可能引发依赖链问题。 |
- 支持广播通信,实现事件驱动机制。 | - 循环依赖可能导致栈溢出。 |
六、高级应用与优化
- 异步通知:使用线程池处理观察者回调,避免阻塞主题线程。
- 事件参数化:通过事件对象(如
VoteEvent
)传递具体数据,增强灵活性。 - 弱引用机制:防止内存泄漏(如使用
WeakReference
存储观察者)。 - 分布式扩展:结合消息队列(如Kafka)实现跨进程观察者。
七、Java内置支持(已过时)
JDK提供java.util.Observable
和Observer
类,但因设计缺陷(如需手动调用setChanged()
)已被标记为过时。推荐自定义实现或使用现代框架(如Spring的ApplicationEvent
)。
总结
观察者模式通过解耦主题与观察者,实现了灵活的通知机制,广泛应用于事件驱动、实时监控等场景。开发者需权衡性能与扩展性,合理设计通知模型(推/拉)和生命周期管理。