Java观察者模式详解

观察者模式详解

一、观察者模式概述

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会自动收到通知并更新。

核心特点

  • 松耦合:主题和观察者之间松耦合
  • 自动通知:状态变化时自动通知观察者
  • 一对多:一个主题可对应多个观察者
  • 动态订阅:可动态添加/删除观察者

二、观察者模式的结构

主要角色

  1. Subject:主题/被观察者,维护观察者列表
  2. Observer:观察者接口,定义更新方法
  3. ConcreteSubject:具体主题,状态变化时通知观察者
  4. ConcreteObserver:具体观察者,实现更新逻辑

三、观察者模式的实现

1. 基本实现(推模型)

复制代码
// 观察者接口
public interface Observer {
    void update(String message);
}

// 主题接口
public interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers();
}

// 具体主题 - 新闻发布中心
public class NewsAgency implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String news;
    
    public void setNews(String news) {
        this.news = news;
        notifyObservers();
    }
    
    public void registerObserver(Observer o) {
        observers.add(o);
    }
    
    public void removeObserver(Observer o) {
        observers.remove(o);
    }
    
    public void notifyObservers() {
        for (Observer o : observers) {
            o.update(news);
        }
    }
}

// 具体观察者 - 新闻频道
public class NewsChannel implements Observer {
    private String name;
    
    public NewsChannel(String name) {
        this.name = name;
    }
    
    public void update(String news) {
        System.out.println(name + " 收到新闻: " + news);
    }
}

// 使用示例
NewsAgency agency = new NewsAgency();
Observer channel1 = new NewsChannel("央视新闻");
Observer channel2 = new NewsChannel("BBC");

agency.registerObserver(channel1);
agency.registerObserver(channel2);

agency.setNews("重大新闻:Java 21发布!");

2. 更灵活的实现(拉模型)

复制代码
// 增强的观察者接口
public interface EnhancedObserver {
    void update(Subject subject);
}

// 增强的主题类
public class WeatherStation implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private float temperature;
    private float humidity;
    
    public void setMeasurements(float temp, float humidity) {
        this.temperature = temp;
        this.humidity = humidity;
        notifyObservers();
    }
    
    // getter方法
    public float getTemperature() { return temperature; }
    public float getHumidity() { return humidity; }
    
    // 其他Subject接口实现...
}

// 具体观察者 - 天气显示
public class CurrentConditionsDisplay implements EnhancedObserver {
    public void update(Subject subject) {
        if (subject instanceof WeatherStation) {
            WeatherStation ws = (WeatherStation) subject;
            System.out.printf("当前温度: %.1f°C, 湿度: %.1f%%\n", 
                ws.getTemperature(), ws.getHumidity());
        }
    }
}

四、观察者模式的应用场景

1. 事件驱动系统

复制代码
// 事件管理器
public class EventManager {
    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 unsubscribe(String eventType, EventListener listener) {
        List<EventListener> eventListeners = listeners.get(eventType);
        if (eventListeners != null) {
            eventListeners.remove(listener);
        }
    }
    
    public void notify(String eventType, String data) {
        List<EventListener> eventListeners = listeners.get(eventType);
        if (eventListeners != null) {
            for (EventListener listener : eventListeners) {
                listener.update(data);
            }
        }
    }
}

2. 股票价格提醒

复制代码
public class StockMarket {
    private Map<String, Double> prices = new HashMap<>();
    private List<StockObserver> observers = new ArrayList<>();
    
    public void addObserver(StockObserver o) {
        observers.add(o);
    }
    
    public void updatePrice(String symbol, double price) {
        prices.put(symbol, price);
        notifyObservers(symbol, price);
    }
    
    private void notifyObservers(String symbol, double price) {
        for (StockObserver o : observers) {
            o.onPriceChanged(symbol, price);
        }
    }
}

public interface StockObserver {
    void onPriceChanged(String symbol, double price);
}

3. Reactor模式(网络事件)

复制代码
public class Reactor {
    private List<EventHandler> handlers = new ArrayList<>();
    
    public void registerHandler(EventHandler handler) {
        handlers.add(handler);
    }
    
    public void handleEvents() {
        while (true) {
            Event event = waitForEvent();
            for (EventHandler h : handlers) {
                if (h.canHandle(event)) {
                    h.handle(event);
                }
            }
        }
    }
}

五、观察者模式的变体

1. 使用Java内置Observable类(已废弃)

复制代码
// 不推荐使用,仅作示例
public class ObservableValue extends java.util.Observable {
    private int value;
    
    public void setValue(int value) {
        this.value = value;
        setChanged();
        notifyObservers(value);
    }
}

2. 使用Java 9+的Flow API

复制代码
import java.util.concurrent.Flow.*;

public class NewsPublisher implements Publisher<String> {
    private SubmissionPublisher<String> publisher = new SubmissionPublisher<>();
    
    public void subscribe(Subscriber<? super String> subscriber) {
        publisher.subscribe(subscriber);
    }
    
    public void publish(String news) {
        publisher.submit(news);
    }
}

public class NewsSubscriber implements Subscriber<String> {
    private Subscription subscription;
    
    public void onSubscribe(Subscription subscription) {
        this.subscription = subscription;
        subscription.request(1);
    }
    
    public void onNext(String item) {
        System.out.println("收到新闻: " + item);
        subscription.request(1);
    }
    
    // 其他方法实现...
}

六、观察者模式的优缺点

优点

  1. 解耦:主题和观察者松耦合
  2. 动态关系:可运行时添加/删除观察者
  3. 广播通信:一对多通知效率高
  4. 开闭原则:新增观察者无需修改主题

缺点

  1. 通知顺序:观察者通知顺序不确定
  2. 性能问题:观察者过多时通知耗时
  3. 循环依赖:可能导致循环调用
  4. 内存泄漏:需手动取消注册

七、最佳实践

  1. 使用弱引用:防止观察者导致内存泄漏
  2. 异步通知:耗时观察者使用异步方式
  3. 批量通知:高频更新可合并通知
  4. 异常处理:单个观察者异常不应影响其他
  5. 考虑线程安全:多线程环境下的安全性

八、总结

观察者模式是事件处理的核心模式,特别适用于:

  • 需要维护对象间的一致性
  • 需要实现事件通知机制
  • 对象变化需要通知其他对象
  • 需要广播通信的场景

在实际开发中,观察者模式常见于:

  • GUI事件处理(如按钮点击)
  • 发布-订阅系统
  • 实时数据监控
  • MVC架构中的模型-视图通信
  • 响应式编程框架

正确使用观察者模式可以实现松耦合的设计,但需要注意避免过度使用导致的性能问题。

相关推荐
正在走向自律2 分钟前
Conda 完全指南:从环境管理到工具集成
开发语言·python·conda·numpy·fastapi·pip·开发工具
啊吧怪不啊吧8 分钟前
C/C++之内存管理
开发语言·汇编·c++
北极象10 分钟前
Go语言处理HTTP下载中EOFFailed
开发语言·http·golang
头发那是一根不剩了12 分钟前
怎么用idea分析hprof文件定位JVM内存问题
java·jvm
让代码飞~17 分钟前
maven项目, idea右上角一直显示gradle的同步标识, 如何去掉
java·maven·intellij-idea
张扬飞舞19 分钟前
IntelliJ IDEA克隆项目失败的解决方法
java·ide·intellij-idea
tyatyatya26 分钟前
MATLAB 自然语言处理入门教程
开发语言·matlab·自然语言处理
一只码代码的章鱼30 分钟前
spring -MVC-02
java·spring·mvc
ziyue757536 分钟前
idea启用lombok
java·intellij-idea·idea·lombok·软件
tmacfrank1 小时前
Java 原生网络编程(BIO | NIO | Reactor 模式)
java·开发语言·网络