小企业网站建设系统哪个好,花灯彩灯制作公司,合肥高端网站建设cnfg,wordpress文章自动更新方法观察者模式
观察者模式属于行为模式#xff0c;个人理解#xff1a;和发布订阅者魔模式是有区别的 细分有两种#xff1a;推模式和拉模式两种#xff0c;具体区别在于推模式会自带推送参数#xff0c;拉模式是在接收通知后要自己获取更新参数
观察者模式#xff08;Obs…观察者模式
观察者模式属于行为模式个人理解和发布订阅者魔模式是有区别的 细分有两种推模式和拉模式两种具体区别在于推模式会自带推送参数拉模式是在接收通知后要自己获取更新参数
观察者模式Observer Pattern的使用场景主要围绕对象间一对多的依赖关系当一个对象被观察者的状态变化需要自动通知其他多个对象观察者时该模式能有效解耦代码。以下是典型的使用场景和案例 应用场景
1. GUI 事件处理
场景用户界面组件如按钮、输入框的状态变化需要触发多个事件监听器。 案例
点击按钮后触发日志记录、界面更新、数据提交等多个操作。输入框内容变化时实时校验输入合法性并更新提示信息。 框架应用Java Swing、Android 的 OnClickListener、JavaScript 的 addEventListener。 2. 实时数据同步
场景数据源的变更需要实时同步到多个客户端或组件。 案例 股票行情系统股价变动时所有关注的投资者界面自动刷新。 在线协作工具如 Google Docs一个用户编辑内容其他用户的视图实时更新。 前端框架如 Vue、React的数据绑定数据变化驱动视图渲染。 一个主界面由好几个子界面垂直布局组成 数据源的变更子界面的数据将实时变化页面由还几个一级标题页面为了解耦和代码管理按照标题差分类结构 3. 状态监控与报警
场景监控系统状态变化并触发相关响应如日志、报警、资源调整。 案例
服务器 CPU 使用率超过阈值时触发邮件报警、记录日志、自动扩容。物联网设备如传感器数据异常时通知用户和管理系统。 4. 游戏开发中的事件系统
场景游戏内事件如角色死亡、任务完成需要触发多模块响应。 案例
玩家生命值降为 0 时触发 UI 更新死亡动画、保存进度、播放音效。成就系统当玩家达成特定条件如击杀 100 个敌人解锁成就并推送通知。 5. 配置或参数动态更新
场景系统配置变更后相关组件需动态调整行为无需重启。 案例
修改系统主题颜色所有界面组件自动切换配色。动态调整日志级别实时生效。 6. 分布式系统中的一致性保证
场景多个服务需要根据核心服务状态变化保持一致性。 案例
电商系统中订单状态变为“已支付”时通知库存服务扣减库存、物流服务生成运单。分布式缓存失效当缓存数据更新通知所有节点清除旧缓存。 观察者模式的优势
解耦被观察者与观察者之间松耦合可独立扩展。灵活性动态添加/移除观察者符合开闭原则。一致性确保所有依赖对象在状态变化时同步更新。 注意事项
性能问题观察者过多或通知逻辑复杂时可能影响性能。循环依赖避免观察者间相互触发导致死循环。内存泄漏某些语言如 Java需手动注销观察者防止对象无法回收。 何时选择观察者模式
一个对象的变化需要通知其他对象且具体通知对象未知或可变。需要减少对象间的直接依赖提升代码复用性和可维护性。跨层级或跨模块通信尤其是事件驱动的系统架构。
推模式代码
#include iostream
#include vector
#include memory// 观察者接口
class Observer {
public:virtual void update(float temperature, float humidity) 0; // 推送具体数据virtual ~Observer() default;
};// 被观察者气象站
class WeatherStation {
private:std::vectorObserver* observers;float temperature;float humidity;public:void addObserver(Observer* observer) {observers.push_back(observer);}void removeObserver(Observer* observer) {// 实际代码中需要更安全的删除逻辑observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());}void setMeasurements(float temp, float hum) {temperature temp;humidity hum;notifyObservers();}private:void notifyObservers() {for (auto observer : observers) {observer-update(temperature, humidity); // 推送数据}}
};// 具体观察者显示屏
class Display : public Observer {
public:void update(float temperature, float humidity) override {std::cout 显示屏更新 - 温度: temperature °C, 湿度: humidity %\n;}
};int main() {WeatherStation station;Display display;station.addObserver(display);station.setMeasurements(25.5f, 60.0f); // 数据变化时自动推送return 0;
}拉模式代码
#include iostream
#include vector
#include memory// 观察者接口
class Observer {
public:virtual void update() 0; // 不推送数据观察者自行拉取virtual ~Observer() default;
};// 被观察者气象站
class WeatherStation {
private:std::vectorObserver* observers;float temperature;float humidity;public:void addObserver(Observer* observer) {observers.push_back(observer);}void removeObserver(Observer* observer) {observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());}void setMeasurements(float temp, float hum) {temperature temp;humidity hum;notifyObservers();}// 观察者通过接口拉取数据float getTemperature() const { return temperature; }float getHumidity() const { return humidity; }private:void notifyObservers() {for (auto observer : observers) {observer-update(); // 仅通知不传递数据}}
};// 具体观察者显示屏
class Display : public Observer {
private:WeatherStation station; // 观察者持有被观察者的引用以拉取数据public:Display(WeatherStation station) : station(station) {}void update() override {float temp station.getTemperature();float hum station.getHumidity();std::cout 显示屏更新 - 温度: temp °C, 湿度: hum %\n;}
};int main() {WeatherStation station;Display display(station); // 观察者需要持有被观察者的引用station.addObserver(display);station.setMeasurements(25.5f, 60.0f); // 数据变化时通知观察者return 0;
}和发布订阅者模式的区别
观察者模式Observer Pattern和发布-订阅模式Pub-Sub Pattern是两种常用于解耦对象间通信的设计模式但它们的设计思想和应用场景有显著区别。以下是两者的核心差异和对比 1. 核心机制与角色关系
特性观察者模式发布-订阅模式通信方式直接通信被观察者Subject直接通知观察者Observer。间接通信发布者Publisher和订阅者Subscriber通过**中介层Broker/Event Bus**交互。角色关系- 被观察者Subject- 观察者Observer- 发布者Publisher- 订阅者Subscriber- 中介层Broker耦合度较高观察者需要直接注册到被观察者依赖其接口。极低发布者和订阅者彼此无感知仅依赖中介层和事件类型。事件路由被观察者自行管理观察者列表并决定通知逻辑。中介层负责事件的路由、过滤和广播例如按主题、标签或内容匹配。 2. 典型代码结构对比
(1) 观察者模式
// 被观察者Subject
class WeatherStation {
private:std::vectorObserver* observers;
public:void addObserver(Observer* observer) { /*注册观察者*/ }void notifyObservers() {for (auto obs : observers) {obs-update(temperature); // 直接调用观察者的接口}}
};// 观察者Observer
class Display : public Observer {
public:void update(float temp) override { /*更新显示*/ }
};(2) 发布-订阅模式
// 中介层Broker
class MessageBroker {
private:std::unordered_mapstd::string, std::vectorSubscriber* topicSubscribers;
public:void subscribe(const std::string topic, Subscriber* sub) { /*按主题订阅*/ }void publish(const std::string topic, const std::string message) {for (auto sub : topicSubscribers[topic]) {sub-onMessage(message); // 通过中介层转发消息}}
};// 订阅者Subscriber
class User : public Subscriber {
public:void onMessage(const std::string msg) override { /*处理消息*/ }
};3. 关键区别
维度观察者模式发布-订阅模式通信方向单向被观察者 → 观察者多向发布者 → 中介层 → 订阅者支持多对多通信动态性观察者需显式注册到具体被观察者订阅者通过中介层动态订阅事件类型如主题、频道扩展性新增事件类型需修改被观察者接口新增事件类型只需在中介层注册无需修改发布者或订阅者适用场景对象间一对多的简单依赖关系如GUI事件、状态同步复杂的多对多通信、跨系统解耦如微服务、消息队列典型应用- 按钮点击事件监听- 数据模型更新UI- 新闻订阅系统- 分布式系统的异步通信- 实时聊天室 4. 场景示例
(1) 观察者模式适用场景 GUI事件处理 按钮被观察者被点击时直接通知所有注册的监听器观察者执行操作。 button.addClickListener(logListener); // 日志监听器
button.addClickListener(uiUpdater); // 界面更新监听器游戏状态同步 角色血量变化时通知UI组件、音效模块、成就系统更新。
(2) 发布-订阅模式适用场景 新闻订阅系统 用户订阅者订阅“科技”主题发布者发布新闻时中介层将消息推送给所有订阅者。 broker.subscribe(科技, user1); // 用户订阅主题
broker.publish(科技, AI新突破); // 发布者发送消息微服务通信 订单服务发布者发布“订单创建”事件库存服务订阅者接收事件并扣减库存。 5. 总结何时选择哪种模式
模式选择条件观察者模式- 对象间关系简单一对多- 需要直接控制通知逻辑- 实时性要求高发布-订阅模式- 系统需要解耦多对多- 动态事件类型和订阅关系- 跨组件或跨系统通信 6. 常见误区 误区1发布-订阅是观察者模式的“升级版”。 纠正两者解决不同问题。观察者模式强调直接通信发布-订阅强调间接通信和解耦。 误区2中介层如 TalkNotifier的存在即表示发布-订阅模式。 纠正观察者模式中的 Subject 也可以视为简单中介但发布-订阅的中介层更独立且支持复杂路由。 误区3发布-订阅必须异步。 纠正发布-订阅可以实现为同步或异步而观察者模式通常是同步的。