当前位置: 首页 > wzjs >正文

一站式做网站企业高中学校网站模板

一站式做网站企业,高中学校网站模板,建设网站申请书,简约的网页设计观察者模式:从博客订阅到消息队列的解耦实践 一、模式核心:用事件驱动实现对象间松耦合 在新闻 APP 中,当热点事件发生时需要实时通知所有订阅用户;在电商系统中,库存变化需触发价格监控模块重新计算。这类场景的核心…

观察者模式:从博客订阅到消息队列的解耦实践

一、模式核心:用事件驱动实现对象间松耦合

在新闻 APP 中,当热点事件发生时需要实时通知所有订阅用户;在电商系统中,库存变化需触发价格监控模块重新计算。这类场景的核心矛盾是:对象间存在依赖关系,但不能硬编码耦合。** 观察者模式(Observer Pattern)** 通过定义「发布 - 订阅」模型,让对象间的通知关系完全解耦,核心解决:

  • 数据变更通知:当主题(Subject)状态变化时,自动通知所有关联的观察者(Observer)
  • 模块解耦:观察者与主题无需互相知道具体实现,仅通过抽象接口交互

核心思想与 UML 类图

img

二、核心实现:构建通用事件通知框架

1. 定义主题接口(Subject)

import java.util.ArrayList;
import java.util.List;public abstract class Subject {private List<Observer> observers = new ArrayList<>();// 注册观察者public void attach(Observer observer) {observers.add(observer);}// 注销观察者public void detach(Observer observer) {observers.remove(observer);}// 通知所有观察者protected void notifyObservers(Object data) {observers.forEach(observer -> observer.update(data));}// 抽象方法:主题状态变化时调用public abstract void updateState(Object newState);
}

2. 实现具体主题(ConcreteSubject)

public class StockSubject extends Subject {private double stockPrice; // 主题状态:股票价格public double getStockPrice() {return stockPrice;}@Overridepublic void updateState(Object newState) {this.stockPrice = (double) newState;notifyObservers(stockPrice); // 状态变化时触发通知}
}

3. 定义观察者接口(Observer)

public interface Observer {// 接收主题通知的更新方法void update(Object data);
}

4. 实现具体观察者(ConcreteObserver)

public class InvestorObserver implements Observer {private String investorName;public InvestorObserver(String name) {this.investorName = name;}@Overridepublic void update(Object data) {double price = (double) data;System.out.println("投资者 " + investorName + " 收到通知:股票价格更新为 " + price);// 执行具体业务逻辑(如触发交易策略)}
}

5. 客户端调用示例

public class ClientDemo {public static void main(String[] args) {// 创建主题与观察者StockSubject stock = new StockSubject();Observer investorA = new InvestorObserver("张三");Observer investorB = new InvestorObserver("李四");// 注册观察者stock.attach(investorA);stock.attach(investorB);// 主题状态变化,触发通知stock.updateState(15.5); // 输出:两位投资者收到价格更新通知stock.detach(investorB); // 注销观察者Bstock.updateState(16.2); // 仅投资者A收到通知}
}

三、进阶:实现异步事件驱动与精准通知

1. 支持泛型的强类型通知

// 定义带泛型的观察者接口
public interface GenericObserver<T> {void update(T data);
}// 主题支持特定类型的事件数据
public class GenericSubject<T> {private List<GenericObserver<T>> observers = new ArrayList<>();public void notifyObservers(T data) {observers.forEach(observer -> observer.update(data));}
}// 使用示例:股票价格变化事件(Double类型)
GenericSubject<Double> stock = new GenericSubject<>();
stock.attach((Double price) -> System.out.println("精准通知:价格" + price));

2. 异步通知机制(解耦通知与业务处理)

public class AsyncSubject<T> extends GenericSubject<T> {private ExecutorService executor = Executors.newFixedThreadPool(5);@Overridepublic void notifyObservers(T data) {// 使用线程池异步执行观察者逻辑executor.submit(() -> super.notifyObservers(data));}
}// 优势:避免主题阻塞,提升系统吞吐量
// 注意:需处理异步带来的线程安全与数据一致性问题

3. 带事件类型的精准通知(基于 Guava EventBus)

// 定义具体事件类型
public class PriceUpdateEvent {private double newPrice;public PriceUpdateEvent(double price) {this.newPrice = price;}// getters...
}// 使用Guava EventBus实现
EventBus eventBus = new EventBus();
eventBus.register(new Object() {@Subscribepublic void onPriceUpdate(PriceUpdateEvent event) {// 仅接收PriceUpdateEvent类型的事件System.out.println("处理价格更新事件:" + event.getNewPrice());}
});
eventBus.post(new PriceUpdateEvent(18.7)); // 精准触发对应观察者

四、框架与源码中的观察者模式实践

1. Spring ApplicationEvent(同步通知)

  • 核心类ApplicationEvent(事件)、ApplicationListener(观察者)、ApplicationEventPublisher(主题)

  • 使用示例:

    // 定义自定义事件
    public class OrderPaidEvent extends ApplicationEvent {private String orderId;public OrderPaidEvent(Object source, String orderId) {super(source);this.orderId = orderId;}
    }// 注册观察者
    @Component
    public class OrderListener implements ApplicationListener<OrderPaidEvent> {@Overridepublic void onApplicationEvent(OrderPaidEvent event) {// 处理订单支付后的业务(如更新库存、发送短信)}
    }// 发布事件
    applicationEventPublisher.publishEvent(new OrderPaidEvent(this, "1001"));
    

2. Android Listener 机制(异步回调)

  • 典型场景:按钮点击事件、网络请求回调

  • 实现原理:

    // 主题(Button)注册观察者(OnClickListener)
    button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 观察者逻辑}
    });
    

3. Kafka 消息队列(分布式观察者)

  • 主题:Kafka 的 Topic(如 “stock-price-topic”)
  • 观察者:Kafka 消费者组(Consumer Group)
  • 优势:支持百万级观察者的分布式通知,实现系统间的松耦合
// Kafka消费者示例(观察者)
KafkaConsumer<String, Double> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Collections.singletonList("stock-price-topic"));
while (true) {ConsumerRecords<String, Double> records = consumer.poll(Duration.ofMillis(100));for (ConsumerRecord<String, Double> record : records) {handlePriceUpdate(record.value()); // 处理通知}
}

五、避坑指南:正确使用观察者模式的 4 个要点

1. 避免内存泄漏(及时注销观察者)

  • ❌ 错误实践:观察者注册后未调用detach(),导致主题持有观察者强引用

  • ✅ 最佳实践:在观察者销毁时(如 Activity 销毁),主动从主题中注销

    @Override
    protected void onDestroy() {super.onDestroy();subject.detach(this); // 注销当前观察者
    }
    

2. 控制通知粒度(避免过度频繁通知)

  • 当主题状态变化频繁时(如实时数据流),增加防抖机制批量通知

    // 防抖示例:1秒内多次变化合并为一次通知
    public void updateState(Object newState) {if (lastUpdateTime + 1000 > System.currentTimeMillis()) {return; // 忽略短时间内的重复通知}lastUpdateTime = System.currentTimeMillis();super.updateState(newState);
    }
    

3. 处理循环依赖(观察者反向修改主题)

  • 当观察者更新时可能再次触发主题状态变化,需增加

    事件防火墙

    public void update(Object data) {if (isProcessingEvent) return; // 避免循环触发isProcessingEvent = true;// 业务逻辑isProcessingEvent = false;
    }
    

4. 反模式:滥用观察者导致复杂度上升

  • 当观察者链过深(如 A→B→C→D)时,改用责任链模式事件总线重构
  • 避免为简单的双向通信使用观察者(直接调用接口更高效)

六、总结:何时该用观察者模式?

适用场景核心特征典型案例
实时数据通知一个对象状态变化需触发多个对象的响应股票行情推送、邮件订阅系统
模块解耦需求对象间存在依赖但不想硬编码关联微服务事件驱动架构、GUI 事件处理
异步事件处理需要将通知与业务逻辑分离消息队列、日志异步写入

观察者模式通过「主题抽象 + 事件驱动」的设计,将对象间的依赖关系从「直接调用」转化为「事件订阅」,这是实现松耦合系统的核心模式之一。下一篇我们将深入探讨状态模式,解析有限状态机在电商订单系统中的设计与实现,敬请期待!

扩展思考:观察者模式 vs 发布 - 订阅模式

两者核心思想相似,但存在关键区别:

模式中介者通知方式应用场景
观察者模式主题直接关联观察者主题主动通知观察者本地模块间通信
发布 - 订阅模式事件总线作为中介发布者与订阅者无直接关联分布式系统、微服务间通信

理解这些差异,有助于在不同架构场景中选择最合适的设计方案。

http://www.dtcms.com/wzjs/840034.html

相关文章:

  • 建微网站需要购买官网主机吗郑州市做网站的
  • 网站可以做被告嘛有没有打代码的网站
  • 中国网库网站介绍旅游网站系统
  • 找网上公司做网站国家企业公示信息系统(全国)官网
  • 国外网站发展建设trs网站建设平台
  • 成品软件网站推荐南宁做网站找哪家
  • 彩票做的最好是个网站好医疗网站制作
  • 网站黑链检测百度热点排行榜
  • 怎么用360做网站跳转企业为什么要培训
  • 个人网站空间申请免费打广告平台有哪些
  • 深圳网站空间深圳市中心在哪里最繁华
  • 安庆微信网站开发百度浏览器下载官方免费
  • 企业网站需要哪些功能三门峡网站建设
  • 如何优化网站内部链接gta5房产网站在建设
  • 贵金属企业网站源码代搭建网站
  • 企业网站优化平台新手销售如何快速入手
  • 设计网站 杭州在线学习网站建设
  • 网络游戏那个网站做的最好网站备案怎么做超链接
  • 经营网站备案1如何做网站推广
  • 网站建设是前端的吗什么网站都有漏洞
  • 男女做暧暧试看网站wordpress md主题
  • 洛阳网站开发培训义乌城市投资建设集团网站
  • 苏州企业网站建设制作服务宝安logo设计
  • 云梦模板网站优缺点1688官网首页官网
  • 翔安区建设局网站网站开发招标方案范本
  • 数据调查的权威网站建立一个app要多少钱
  • 网站代运营公司排名企业公示信息
  • 好看又免费的图片素材网站网站动态标签
  • 广州网站建设公司推荐乐云seo如何去推广自己的产品
  • 打工网站校企合作建设中华网