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架构中的模型-视图通信
  • 响应式编程框架

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

相关推荐
水w31 分钟前
【Android Studio】解决报错问题Algorithm HmacPBESHA256 not available
android·开发语言·android studio
冷琅辞1 小时前
Elixir语言的云计算
开发语言·后端·golang
Mryan20052 小时前
解决GraalVM Native Maven Plugin错误:JAVA_HOME未指向GraalVM Distribution
java·开发语言·spring boot·maven
Naomi5212 小时前
自定义汇编语言(Custom Assembly Language) 和 Unix & Git
服务器·开发语言·git·unix
烂蜻蜓2 小时前
C 语言命令行参数:让程序交互更灵活
c语言·开发语言·交互
VX_CXsjNo12 小时前
免费送源码:Java+SSM+Android Studio 基于Android Studio游戏搜索app的设计与实现 计算机毕业设计原创定制
java·spring boot·spring·游戏·eclipse·android studio·android-studio
zm-v-159304339862 小时前
解锁 DeepSeek 与 Matlab:攻克科研难题的技术利刃
开发语言·matlab·信息可视化
ylfhpy2 小时前
Java面试黄金宝典33
java·开发语言·数据结构·面试·职场和发展·排序算法
照书抄代码2 小时前
C++11可变参数模板单例模式
开发语言·c++·单例模式·c++11
No0d1es2 小时前
CCF GESP C++编程 四级认证真题 2025年3月
开发语言·c++·青少年编程·gesp·ccf·四级·202503