全部学科
Python全栈
python
NodeJS全栈
nodejs
📅 2026-05-11 6 分钟 ✍️ juanwangdev

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"));

观察者模式优点

  1. Subject与Observer解耦
  2. 支持广播通信
  3. 符合开闭原则

观察者模式缺点

  1. Observer过多影响性能
  2. 无序通知可能导致逻辑问题
  3. 循环依赖导致死循环

注意事项

避免循环调用导致死循环

异步通知注意线程安全

观察者过多可考虑异步处理

Spring事件机制是观察者模式的应用

要点总结

  1. 观察者模式定义一对多依赖,自动通知更新
  2. Subject管理观察者,状态变化时通知
  3. Observer定义更新接口,收到通知执行逻辑
  4. 推模型传递数据,拉模型主动获取
  5. 适用于事件处理、消息订阅、GUI事件
想在手机上练习这篇文章的配套题目?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码
← 上一篇 Java装饰器模式
下一篇 → Java解释器模式
扫码体验小程序
加载中
想在手机上刷题学习?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码