温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

观察者模式java实现要注意什么

发布时间:2026-10-24 12:44:24 来源:亿速云 阅读:91 作者:小樊 栏目:编程语言

在 Java 中实现观察者模式(Observer Pattern)时,有几个关键点需要特别注意,既能保证功能正确,也能避免常见的坑。下面从设计、线程安全、内存泄漏、性能几个方面来说明。


一、基本实现方式

Java 本身提供了支持:

  • java.util.Observable(已废弃,不推荐)
  • java.util.Observer(已废弃)

推荐方式:

  • 自己定义接口
  • 或使用 java.util.EventListener
  • 或使用 java.util.concurrent / RxJava / Spring 事件机制

简单示例

interface Observer {
    void update(String message);
}

class Subject {
    private List<Observer> observers = new ArrayList<>();

    public void addObserver(Observer o) {
        observers.add(o);
    }

    public void removeObserver(Observer o) {
        observers.remove(o);
    }

    public void notifyObservers(String msg) {
        for (Observer o : observers) {
            o.update(msg);
        }
    }
}

二、需要重点注意的问题

1️⃣ 避免 NullPointerException

在通知观察者时,观察者列表可能被并发修改:

for (Observer o : new ArrayList<>(observers)) {
    o.update(msg);
}

或使用 CopyOnWriteArrayList


2️⃣ 线程安全问题(非常重要)

如果:

  • 多线程添加/删除观察者
  • 多线程触发通知

需要保证:

  • 观察者集合线程安全
  • 通知过程不阻塞过久

✅ 推荐:

private final List<Observer> observers =
        new CopyOnWriteArrayList<>();

❌ 不推荐:

synchronized (this) { ... } // 容易死锁或性能差

3️⃣ 防止内存泄漏(观察者未注销)

最常见问题:

  • 观察者被回收不了
  • Subject 持有 Observer 强引用

✅ 解决方法:

  • 提供 removeObserver
  • 在生命周期结束时主动注销(如 Activity / Bean 销毁)
@Override
public void destroy() {
    subject.removeObserver(this);
}

✅ 进阶:

  • 使用 WeakReference<Observer>(需谨慎)

4️⃣ 通知顺序不要依赖

不要假设:

observerA 一定先于 observerB 执行

除非业务明确需要顺序(可使用队列)


5️⃣ 避免观察者执行耗时操作

观察者方法里:

  • ❌ 不要做 IO / 网络 / 睡眠
  • ✅ 可异步处理
executor.submit(() -> o.update(msg));

6️⃣ 防止“通知中修改观察者列表”

错误示例:

public void update() {
    subject.removeObserver(this); // 可能 ConcurrentModificationException
}

✅ 解决:

  • 延迟删除
  • 使用并发集合

7️⃣ 事件对象设计要稳定

通知时传参:

  • 不要用裸 String
  • 用不可变事件对象
class Event {
    private final String type;
    private final Object data;
}

三、Java 中的高级替代方案

✅ Spring 事件

@EventListener
public void handle(UserCreatedEvent e) {}

✅ Guava EventBus

eventBus.register(this);
eventBus.post(event);

✅ RxJava / Reactor

适合复杂异步流


四、总结 checklist ✅

实现观察者模式要注意:

  • [ ] 使用线程安全的观察者集合
  • [ ] 防止内存泄漏(及时注销)
  • [ ] 通知时避免 ConcurrentModification
  • [ ] 观察者方法不阻塞
  • [ ] 不依赖通知顺序
  • [ ] 事件对象设计清晰稳定

如果你愿意,我可以:

  • 写一个线程安全完整示例
  • 对比 Observer vs 发布订阅
  • 结合 Spring / Android 场景讲
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手