本文目录导读:

我将为您提供几个Java观察者模式的案例,从基础到进阶。
基础案例:天气站
这是最经典的观察者模式例子。
import java.util.ArrayList;
import java.util.List;
// 观察者接口
interface Observer {
void update(float temperature, float humidity, float pressure);
}
// 主题接口
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 具体主题:天气数据
class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
// 当数据变化时调用
public void measurementsChanged() {
notifyObservers();
}
// 模拟数据变化
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
// 具体观察者1:当前条件显示
class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("当前条件: " + temperature + "°C, " + humidity + "% 湿度");
}
}
// 具体观察者2:统计显示
class StatisticsDisplay implements Observer {
private float maxTemp = 0;
private float minTemp = 200;
private float tempSum = 0;
private int numReadings = 0;
@Override
public void update(float temperature, float humidity, float pressure) {
tempSum += temperature;
numReadings++;
if (temperature > maxTemp) maxTemp = temperature;
if (temperature < minTemp) minTemp = temperature;
display();
}
public void display() {
System.out.println("统计结果: " + (tempSum / numReadings)
+ " 平均温度, " + maxTemp + " 最高温度, " + minTemp + " 最低温度");
}
}
// 测试类
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
StatisticsDisplay statisticsDisplay = new StatisticsDisplay();
weatherData.registerObserver(currentDisplay);
weatherData.registerObserver(statisticsDisplay);
System.out.println("=== 第一次更新 ===");
weatherData.setMeasurements(25.5f, 65, 1013.2f);
System.out.println("\n=== 第二次更新 ===");
weatherData.setMeasurements(26.8f, 70, 1014.5f);
// 移除一个观察者
weatherData.removeObserver(statisticsDisplay);
System.out.println("\n=== 第三次更新 (移除统计显示后) ===");
weatherData.setMeasurements(24.2f, 68, 1012.8f);
}
}
进阶案例:消息通知系统
使用Lambda表达式和函数式接口简化实现。
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
// 事件类型
enum EventType {
NEW_MESSAGE,
FRIEND_REQUEST,
SYSTEM_ALERT
}
// 事件类
class Event {
private EventType type;
private String message;
private Object data;
public Event(EventType type, String message, Object data) {
this.type = type;
this.message = message;
this.data = data;
}
public EventType getType() { return type; }
public String getMessage() { return message; }
public Object getData() { return data; }
}
// 事件总线
class EventBus {
private static EventBus instance;
private List<Consumer<Event>> listeners = new ArrayList<>();
private EventBus() {}
public static EventBus getInstance() {
if (instance == null) {
instance = new EventBus();
}
return instance;
}
public void subscribe(Consumer<Event> listener) {
listeners.add(listener);
}
public void unsubscribe(Consumer<Event> listener) {
listeners.remove(listener);
}
public void publish(Event event) {
listeners.forEach(listener -> {
try {
listener.accept(event);
} catch (Exception e) {
System.err.println("处理事件时出错: " + e.getMessage());
}
});
}
}
// 消息服务
class MessagingService {
private List<String> users = new ArrayList<>();
public void sendMessage(String user, String message) {
Event event = new Event(EventType.NEW_MESSAGE,
"用户 " + user + " 发送了消息: " + message, user);
EventBus.getInstance().publish(event);
}
public void addUser(String username) {
users.add(username);
Event event = new Event(EventType.SYSTEM_ALERT,
"新用户加入: " + username, username);
EventBus.getInstance().publish(event);
}
}
// 客户端示例
public class EventSystemDemo {
public static void main(String[] args) {
EventBus eventBus = EventBus.getInstance();
// UI组件1:聊天界面
eventBus.subscribe(event -> {
if (event.getType() == EventType.NEW_MESSAGE) {
System.out.println("[聊天界面] 收到新消息: " + event.getMessage());
}
});
// UI组件2:系统通知栏
eventBus.subscribe(event -> {
if (event.getType() == EventType.SYSTEM_ALERT) {
System.out.println("[通知栏] !! 系统通知: " + event.getMessage());
}
});
// 使用Lambda表达式注册观察者
eventBus.subscribe(event -> {
if (event.getType() == EventType.NEW_MESSAGE) {
System.out.println("[日志记录] 记录消息: " + event.getMessage());
}
});
// 测试
MessagingService service = new MessagingService();
System.out.println("=== 添加用户 ===");
service.addUser("张三");
System.out.println("\n=== 发送消息 ===");
service.sendMessage("张三", "大家好!");
System.out.println("\n=== 再发送一条消息 ===");
service.sendMessage("李四", "晚上好");
}
}
完整的企业级案例:股票监控系统
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
// 观察者模式结合传统实现和现代特性
// 股票类
class Stock {
private String symbol;
private double price;
public Stock(String symbol, double price) {
this.symbol = symbol;
this.price = price;
}
public String getSymbol() { return symbol; }
public double getPrice() { return price; }
@Override
public String toString() {
return symbol + " $" + price;
}
}
// 股票市场(主题)
class StockMarket {
private Map<String, Double> stocks = new HashMap<>();
private List<StockObserver> observers = new CopyOnWriteArrayList<>();
public interface StockObserver {
void onPriceChange(Stock stock);
}
public void registerObserver(StockObserver observer) {
observers.add(observer);
}
public void unregisterObserver(StockObserver observer) {
observers.remove(observer);
}
public void addStock(Stock stock) {
stocks.put(stock.getSymbol(), stock.getPrice());
notifyObservers(stock);
}
public void updatePrice(String symbol, double newPrice) {
Double currentPrice = stocks.get(symbol);
if (currentPrice != null && currentPrice != newPrice) {
stocks.put(symbol, newPrice);
Stock stock = new Stock(symbol, newPrice);
notifyObservers(stock);
}
}
private void notifyObservers(Stock stock) {
observers.forEach(observer -> observer.onPriceChange(stock));
}
}
// 具体观察者:个人投资者
class Investor implements StockMarket.StockObserver {
private String name;
private Set<String> monitoredStocks;
private double threshold; // 价格阈值
public Investor(String name, double threshold, String... monitoredStocks) {
this.name = name;
this.threshold = threshold;
this.monitoredStocks = new HashSet<>(Arrays.asList(monitoredStocks));
}
@Override
public void onPriceChange(Stock stock) {
if (monitoredStocks.contains(stock.getSymbol())) {
double change = Math.abs(stock.getPrice() - threshold);
if (change > threshold * 0.1) { // 超过10%的波动
System.out.println(name + " 注意: " + stock + " 波动较大!");
} else {
System.out.println(name + " 收到通知: " + stock + " 价格已更新");
}
}
}
}
// 具体观察者:量化交易机器人
class TradingBot implements StockMarket.StockObserver {
private String botName;
private List<String> tradableStocks;
private boolean autoTrade = true;
public TradingBot(String botName, List<String> tradableStocks) {
this.botName = botName;
this.tradableStocks = tradableStocks;
}
@Override
public void onPriceChange(Stock stock) {
if (tradableStocks.contains(stock.getSymbol())) {
if (stock.getPrice() > 100) {
System.out.println("[交易机器人 " + botName + "] 建议买入 " + stock);
} else if (stock.getPrice() < 50) {
System.out.println("[交易机器人 " + botName + "] 建议卖出 " + stock);
} else {
System.out.println("[交易机器人 " + botName + "] 价格平稳,不操作");
}
}
}
}
// 主体测试
public class StockMarketDemo {
public static void main(String[] args) {
StockMarket market = new StockMarket();
// 创建观察者
Investor alice = new Investor("Alice", 100, "AAPL", "GOOGL");
Investor bob = new Investor("Bob", 50, "MSFT");
TradingBot bot1 = new TradingBot("Bot-1", Arrays.asList("AAPL", "MSFT"));
// 注册观察者
market.registerObserver(alice);
market.registerObserver(bob);
market.registerObserver(bot1);
// 模拟股票变化
System.out.println("=== 添加新股票 ===");
market.addStock(new Stock("AAPL", 150.0));
System.out.println("\n=== 更新股票价格 ===");
market.updatePrice("AAPL", 160.0);
market.updatePrice("GOOGL", 2500.0);
market.updatePrice("MSFT", 45.0);
market.updatePrice("TSLA", 700.0);
// 取消注册
market.unregisterObserver(bob);
System.out.println("\n=== 更新价格(Bob已取消注册)===");
market.updatePrice("MSFT", 55.0);
market.updatePrice("AAPL", 165.0);
// 显示当前状态
System.out.println("\n=== 最终状态 ===");
// 这里没有直接访问内部Map的方法,可以添加
}
}
关键要点
观察者模式的四大角色
- Subject(主题): 维护观察者列表,发送通知
- ConcreteSubject(具体主题): 存储状态,状态变化时通知观察者
- Observer(观察者): 定义更新接口
- ConcreteObserver(具体观察者): 实现更新逻辑
实现方式
- 传统方式: 使用接口和类
- Lambda方式: 使用函数式接口简化代码
- 事件总线: 解耦生产者与消费者
应用场景
- GUI事件监听
- 消息推送系统
- 日志记录系统
- 缓存同步
- 实时数据监控
优点
- 解耦,主题和观察者松耦合
- 支持广播通信
- 易于扩展
缺点
- 通知顺序不可控
- 可能导致性能问题(大量观察者)
- 循环依赖风险
性能优化建议
- 使用CopyOnWriteArrayList避免并发问题
- 使用java.util.Observer接口(已过时,建议自定义)
- 考虑批量处理和异步通知
这些案例展示了观察者模式在不同场景下的应用,从简单的天气站到复杂的事件驱动系统,选择哪种实现取决于您的具体需求。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播