Java观察者模式
观察者模式定义对象间一对多依赖,当对象改变时,依赖对象自动收到通知。
模式定义
意图:定义对象间一对多依赖,当一个对象改变时,依赖对象自动更新。
适用场景
- 事件处理系统
- 消息订阅
- 数据绑定
- GUI事件响应
模式结构
Subject(被观察者)
Java
public interface Subject {
void attach(Observer observer);
void detach(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 attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state); // 推模型
}
}
}
Observer(观察者)
Java
public interface Observer {
void update(String state); // 推模型
}
public class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String state) {
System.out.println(name + "收到通知: " + state);
}
}
使用示例
Java
ConcreteSubject subject = new ConcreteSubject();
Observer observer1 = new ConcreteObserver("观察者1");
Observer observer2 = new ConcreteObserver("观察者2");
subject.attach(observer1);
subject.attach(observer2);
subject.setState("新状态");
// 观察者1收到通知: 新状态
// 观察者2收到通知: 新状态
推模型 vs 拉模型
| 模型 | 特点 | update参数 |
|---|---|---|
| 推模型 | Subject推送数据 | 传递具体数据 |
| 拉模型 | Observer主动获取 | 传递Subject引用 |
Java
// 拉模型
public interface Observer {
void update(Subject subject);
}
public class ConcreteObserver implements Observer {
@Override
public void update(Subject subject) {
String state = ((ConcreteSubject) subject).getState(); // 拉取
System.out.println("收到通知: " + state);
}
}
Java内置观察者
Java提供Observable类和Observer接口(已废弃,但仍可用):
Java
public class NewsAgency extends Observable {
private String news;
public void setNews(String news) {
this.news = news;
setChanged(); // 标记已改变
notifyObservers(news); // 通知观察者
}
}
public class NewsReader implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("收到新闻: " + arg);
}
}
// 使用
NewsAgency agency = new NewsAgency();
agency.addObserver(new NewsReader());
agency.setNews("重大新闻");
实际应用示例
事件监听
Java
public interface EventListener {
void onEvent(Event event);
}
public class EventBus {
private Map<String, List<EventListener>> listeners = new HashMap<>();
public void subscribe(String eventType, EventListener listener) {
listeners.computeIfAbsent(eventType, k -> new ArrayList())
.add(listener);
}
public void publish(String eventType, Event event) {
List<EventListener> list = listeners.get(eventType);
if (list != null) {
for (EventListener listener : list) {
listener.onEvent(event);
}
}
}
}
Spring事件机制
Java
// 自定义事件
public class CustomEvent extends ApplicationEvent {
private String message;
public CustomEvent(Object source, String message) {
super(source);
this.message = message;
}
public String getMessage() { return message; }
}
// 事件监听器
@Component
public class CustomEventListener {
@EventListener
public void handleCustomEvent(CustomEvent event) {
System.out.println("收到事件: " + event.getMessage());
}
}
// 发布事件
@Autowired
private ApplicationEventPublisher publisher;
publisher.publishEvent(new CustomEvent(this, "Hello"));
观察者模式优点
- Subject与Observer解耦
- 支持广播通信
- 符合开闭原则
观察者模式缺点
- Observer过多影响性能
- 无序通知可能导致逻辑问题
- 循环依赖导致死循环
注意事项
避免循环调用导致死循环
异步通知注意线程安全
观察者过多可考虑异步处理
Spring事件机制是观察者模式的应用
要点总结
- 观察者模式定义一对多依赖,自动通知更新
- Subject管理观察者,状态变化时通知
- Observer定义更新接口,收到通知执行逻辑
- 推模型传递数据,拉模型主动获取
- 适用于事件处理、消息订阅、GUI事件
📝 发现内容有误?点击此处直接编辑