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

观察者设计模式知多少

目录

目标

概述

实现 

推设计模式

拉设计模式

被动观察者设计模式


目标

熟悉观察者设计模式,了解观察者设计模式的使用场景、具体实现(包括:推设计模式、拉设计模式、被动观察者设计模式)


概述

一、行为设计模式

行为设计模式是设计模式的一种类型。该类型的设计模式关注的重点在于对象的行为(通信和交互),而非对象的创建方式。较为常见的行为设计模式有:观察者模式、策略模式、命令模式、责任链模式等。优点是减少了对象之间的耦合度

二、观察者设计模式

对象之间存在一对多的依赖关系,多个观察者对象同时监听某一个主题对象(被观察者对象)。当主题对象的状态发生改变时会通知其他观察者对象。主题对象实现思路:

  1. 主题对象类定义一个集合observerList用来保存多个观察者对象。
  2. 定义观察者对象注册到主题对象的方法、主题对象从注册表中剔除指定观察者对象的方法、定义通知方法。
  3. 当对象状态发生改变时调用该方法,以遍历observerList的方式通知所有观察者对象。

优点

  1. 被观察者使用注册表的方式囊括了所有观察者,降低了观察者对象和被观察者对象之间的依赖关系,提高了系统的扩展性和可维护性。
  2. 被观察者类提供了注册,剔除的方法,使得代码扩展性增强。
  3. 该模式实现了事件驱动的方式,使业务实现方案变得更灵活。

缺点

  1. 观察者过多会导致内存开销大。
  2. 容易发生循环依赖问题。

种类

  • 推设计模式:最简单的模式,指被观察者主动将状态推送给观察者。
  • 拉设计模式:被观察者只告知观察者状态发生了改变,观察者需要通过主动去“拉”的方式,获取被观察者的具体状态。
  • 被动观察者设计模式:引入了一个中介者对象来协调主题对象和观察者之间的交互。主题对象不再直接通知观察者,而是将状态变化通知给中介者对象,由中介者对象负责通知观察者。

三、使用场景

  • 一个对象发生改变需要通知其他对象,其他对象可以自由选择监听或者不监听。
  • 一个对象发生改变需要通知其他对象,其他对象的类型和数量不确定时。

四、列举观察者模式在成熟的框架中的应用

  • 在RabbitMQ中,Exchange和Queue之间的绑定关系。
  • Java AWT/Swing事件处理机制。
  • Spring Framework事件机制。
  • Java Message Service(JMS)。

实现 

推设计模式

需求

多个用户订阅了天气预报系统,则天气预报作为被观察者对象,一旦天气预报发生更新,则订阅者需要马上感知并获取天气预报状态。

观察者接口

package com.ctx.observer.push;// 定义用户作为观察者对象
interface Observer {public void update(String weather);
}

观察者接口实现类

package com.ctx.observer.push;// 实现具体的观察者对象
class User implements Observer {private String name;public User(String name) {this.name = name;}// 接收天气预报信息public void update(String weather) {System.out.println(name + "收到天气预报信息:" + weather);}
}

被观察者类

package com.ctx.observer.push;import java.util.ArrayList;
import java.util.List;// 定义天气预报机构作为主题对象
class WeatherForecast {private List<Observer> observers = new ArrayList<Observer>();private String weather;// 注册观察者对象public void registerObserver(Observer observer) {observers.add(observer);}// 移除观察者对象public void removeObserver(Observer observer) {observers.remove(observer);}// 通知所有观察者对象public void notifyObservers() {for (Observer observer : observers) {observer.update(weather);}}// 更新天气预报信息public void setWeather(String weather) {this.weather = weather;notifyObservers();}
}

调用测试类

package com.ctx.observer.push;// 测试代码
public class Test {public static void main(String[] args) {WeatherForecast weatherForecast = new WeatherForecast();// 创建多个用户作为观察者对象User user1 = new User("张三");User user2 = new User("李四");User user3 = new User("王五");// 注册观察者对象weatherForecast.registerObserver(user1);weatherForecast.registerObserver(user2);weatherForecast.registerObserver(user3);// 发布天气预报信息weatherForecast.setWeather("今天晴朗,温度26℃");// 移除观察者对象weatherForecast.removeObserver(user2);// 发布天气预报信息weatherForecast.setWeather("明天有雨,温度22℃");}
}

拉设计模式

需求

多个用户订阅了新闻频道,则新闻频道作为被观察者对象,一旦新闻频道发生更新,则订阅者需要马上感知新闻频道发生了更新。但是具体更新了什么新闻,需要由用户主动去获取。

观察者接口

package com.ctx.observer.pull;// 定义观察者对象
interface Observer {void update(News news);
}

观察者接口实现类

package com.ctx.observer.pull;// 定义具体的观察者对象(居民对象)
class Resident implements Observer {private String name;public Resident(String name) {this.name = name;}// 拉模式:观察者主动获取消息内容public void update(News news) {System.out.println(name + "收到消息: " + news.getNewsContent());}public String getName() {return name;}
}

被观察者类

package com.ctx.observer.pull;import java.util.ArrayList;
import java.util.List;// 定义被观察者对象(新闻对象是被观察者)
class News {private List<Observer> observers = new ArrayList<>();private String newsContent;public void addObserver(Observer observer) {observers.add(observer);}public void removeObserver(Observer observer) {observers.remove(observer);}public void setNewsContent(String newsContent) {this.newsContent = newsContent;notifyObservers();}// 通知观察者更新消息private void notifyObservers() {for (Observer observer : observers) {observer.update(this);}}// 获取消息内容public String getNewsContent() {return newsContent;}
}

调用测试类

package com.ctx.observer.pull;public class Test {public static void main(String[] args) {News news = new News();// 居民订阅新闻Resident resident1 = new Resident("张三");Resident resident2 = new Resident("李四");news.addObserver(resident1);news.addObserver(resident2);// 设置新闻内容,观察者拉取消息内容news.setNewsContent("今天是个好日子!");}
}

被动观察者设计模式

需求

患者住院治疗,则患者作为被观察者,医生和护士作为观察者。但是医生和护士不能一直陪在患者身边,为了及时响应,医院安装了医疗监护系统,一旦患者有需要则通过医疗监护系统通知医生和护士,医疗监护系统起到了中介者的作用,它来协调观察者和被观察者之间的交互。

观察者接口

package com.ctx.observer.passive;// 定义观察者接口
interface Observer {void update(); // 更新观察者状态
}

观察者接口实现类

package com.ctx.observer.passive;// 定义具体的观察者,即医生和护士类
class MedicalStaff implements Observer {private String name;private Subject patient;public MedicalStaff(String name, Subject patient) {this.name = name;this.patient = patient;patient.registerObserver(this); // 注册观察者}@Overridepublic void update() {String condition = ((Patient) patient).getCondition(); // 获取被观察者状态System.out.println(name + "收到病人病情更新通知,病情为:" + condition); // 处理病情变化}
}

中介者

package com.ctx.observer.passive;// 定义中介者,即医疗监护系统类
class MedicalMonitor {private Subject patient;public MedicalMonitor(Subject patient) {this.patient = patient;}public void setPatientCondition(String condition) {((Patient) patient).setCondition(condition); // 更新被观察者状态}
}

被观察者接口

package com.ctx.observer.passive;// 定义被观察者接口
interface Subject {void registerObserver(Observer observer); // 注册观察者void removeObserver(Observer observer); // 移除观察者void notifyObservers(); // 通知观察者
}

被观察者接口实现类

package com.ctx.observer.passive;import java.util.ArrayList;
import java.util.List;// 定义具体的被观察者,即病人类
class Patient implements Subject {private List<Observer> observers; // 观察者列表private String condition; // 病情public Patient() {observers = new ArrayList<>();}@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(); // 通知每个观察者更新状态}}public void setCondition(String condition) {this.condition = condition;notifyObservers(); // 状态变化后通知所有观察者更新状态}public String getCondition() {return condition;}
}

调用测试类

package com.ctx.observer.passive;// 测试
public class Test {public static void main(String[] args) {Patient patient = new Patient(); // 创建被观察者MedicalMonitor monitor = new MedicalMonitor(patient); // 创建中介者MedicalStaff doctor = new MedicalStaff("张医生", patient); // 创建观察者MedicalStaff nurse = new MedicalStaff("李护士", patient); // 创建观察者monitor.setPatientCondition("发热"); // 病人状态变化,触发通知patient.removeObserver(doctor); // 病人移除一个观System.out.println("--------------------------");monitor.setPatientCondition("感冒"); // 病人状态变化,触发通知}
}

相关文章:

观察者设计模式知多少

目录 目标 概述 实现 推设计模式 拉设计模式 被动观察者设计模式 目标 熟悉观察者设计模式&#xff0c;了解观察者设计模式的使用场景、具体实现&#xff08;包括&#xff1a;推设计模式、拉设计模式、被动观察者设计模式&#xff09;。 概述 一、行为设计模式 行为设…...

Flink之TaskManager内存解析

一、CK失败 Flink任务的checkpoint操作失败大致分为两种情况&#xff0c;ck decline和ck expire: &#xff08;1&#xff09;ck decline 发生ck decline情况时&#xff0c;我们可以通过查看JobManager.log或TaskManager.log查明具体原因。其中有一种特殊情况为ck cancel&…...

为何越来越多人不喜欢“试用期六个月”的公司?网友:感觉不靠谱

众所周知&#xff0c;任何一份工作都有试用期&#xff0c;一般是三月左右。但如果你遇到试用期达到半年的公司&#xff0c;你会不会进入&#xff1f; 近日&#xff0c;就有人遇到了此类公司&#xff0c;并对是否要进入该公司犹豫不决。他在论坛上发帖求助&#xff1a;大家是怎…...

单例模式的四种创建方式

前言 单例模式是日常开发中最常见的一种设计模式&#xff0c;常用来做为池对象&#xff0c;或者计数器之类的需要保证全局唯一的场景。 单例模式的目的是保证在整个程序中只存在一个对象实例&#xff0c;使用单例一个前提条件就是构造器私有化&#xff0c;不允许通过new 对象…...

Nginx+Keepalived 中的脑裂现象

如何解决和预防 NginxKeepalived 中会出现的脑裂现象? Nginx是一种高性能的Web服务器和反向代理服务器&#xff0c;可以处理大量并发请求。Keepalived是一种开源软件&#xff0c;用于实现IP负载均衡和故障转移。在Nginx和Keepalived结合使用时&#xff0c;可以通过将多个Ngin…...

04 KVM虚拟化网络概述

文章目录 04 KVM虚拟化网络概述4.1 Linux Bridge4.2 Open vSwitch 04 KVM虚拟化网络概述 为了使虚拟机可以与外部进行网络通信&#xff0c;需要为虚拟机配置网络环境。KVM虚拟化支持Linux Bridge、Open vSwitch网桥等多种类型的网桥。如图1所示&#xff0c;数据传输路径为“虚…...

110页智慧农业解决方案(农业信息化解决方案)(ppt可编辑)

本资料来源公开网络&#xff0c;仅供个人学习&#xff0c;请勿商用&#xff0c;如有侵权请联系删除。 第一部分 智慧农业概述 智慧农业以农业资源为基础、市场为导向、效益为中心、产业化为抓手&#xff0c;面向农业管理部门、农技推广部门、农业企业、农业园区和基地、农业专…...

Java知识体系及聊天室程序

Java知识体系结构梳理如下&#xff1a; 基础语法&#xff1a;Java的基本语法&#xff0c;包括数据类型、运算符、控制语句、数组等。 面向对象编程&#xff1a;Java是一种面向对象的编程语言&#xff0c;需要掌握类、对象、继承、多态等概念。 异常处理&#xff1a;Java提供了…...

java的详细发展历程

Java是一种跨平台、面向对象的编程语言&#xff0c;具有简单性、可移植性、安全性等特点。Java的历史可以追溯到上世纪90年代初期&#xff0c;以下是Java的详细发展历程&#xff1a; 1991年&#xff0c;Sun Microsystems公司的James Gosling和他的团队开始开发一种名为Oak的编程…...

丢石子

I 一堆石子有n个,两人轮流取.先取者第1次可以取任意多个&#xff0c;但不能全部取完.以后每次取的石子数不能超过上次取子数的2倍。取完者胜.先取者负输出"Second win".先取者胜输出"First win". 思路&#xff1a; 任何正整数都可以表示为不连续斐波那契…...

skywalking手动上报一些指标信息

skywalking的相关概念我就不介绍了&#xff0c;有兴趣可以参看官网文档 以下提供以下简单示例手工上报一些对问题排查比较有用的一些信息。当然这些内容你也可以写成探针插件的形式&#xff0c;怎么开发探针插件也自行参考官方文档。此处仅在项目框架层面提供一些简单的示例&am…...

NUMA详解

目录 NUMA简介 NUMA开启与关闭 查看系统是否支持 关闭方法 numactl --hardware介绍 没有安装numactl工具下查看NUMA架构节点数&#xff1a; 查看每个NUMA节点的CPU使用情况&#xff1a; 看每个NUMA节点的内存使用情况&#xff1a; 查看NUMA下指定进程的运行情况 创建…...

H68K在Armbina系统下开AP

背景需求替代路由器,网上找了一大堆都不行 最后成功开启了AP 参考了两篇文章, 一篇是如何创建热点, 一篇是如何开启5G 树莓派4B创建5Ghz WiFi热点 – 风声 https://www.hncldz.com/2020/02/01/%e6%a0%91%e8%8e%93%e6%b4%be4b%e5%88%9b%e5%bb%ba5ghz-wifi%e7%83%ad%e7%82%b…...

还不懂Redis?看完这个故事就明白了!

还不懂Redis?看完这个故事就明白了! 我是Redis 你好,我是Redis,一个叫Antirez的男人把我带到了这个世界上。 说起我的诞生,跟关系数据库MySQL还挺有渊源的。 在我还没来到这个世界上的时候,MySQL过的很辛苦,互联网发展的越来越快,它容纳的数据也越来越多,用户请求也…...

Haproxy负载均衡集群

1.Haproxy支持四层和七层 2.haproxy常用的调度算法&#xff1f; 3.LSV/NGINX/HAPROXT的区别&#xff1f; 4. 5.Haproy负载均衡部署 实验需求 利用Haproxy的运用配置出负载均衡调度器&#xff0c;以此来调用两台Nginx服务器进行工作 实验所需组件 Haproxy服务器&#xff1a;192…...

17.计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度

说明书 MATLAB代码&#xff1a;计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度 关键词&#xff1a;碳捕集 虚拟电厂 需求响应 优化调度 电转气协同调度 参考文档&#xff1a;《计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度》完全复现 仿真平台&#xff1a…...

企业数字化管理中,数据治理到底怎么“治”

随着信息化、数字化的理念、技术及其应用在社会的方方面面进行扩散&#xff0c;数据的规模和丰富程度已经达到了一个新的高度&#xff0c;所以当下如何更进一步利用好数据&#xff0c;充分发挥数据的价值&#xff0c;将其真正变为高质量的数据资产成为了企业要面对的重要问题&a…...

《HelloGitHub》第 85 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 https://github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 …...

自动驾驶人机交互HMI产品技术方案

1. 概述 1.1 目的 本文档描述集卡自动驾驶系统中HMI产品的技术方案,设计人员遵循本方案进行设计,为项目开发实施提供技术方案保障。 1.2 范围 本文档适用于HMI产品项目。本文档用于指导HMI产品项目的UI、前端开发过程。 1.3 术语与缩写 术语/缩写 描述 HMI...

开发感悟20230426

一、element-ui样式设置 1. 可以直接在css中写个样式文件&#xff0c;把对应的类名改写样式&#xff0c;然后在main.js中引用&#xff0c;可以覆盖上面的&#xff0c;如果想给element-ui设置样式&#xff0c;不用设置deep了 2.可以直接修改引入的element-ui的样式&#xff0c…...

C和C++的区别

C和C的区别 1、面向对象编程&#xff1a;C是面向对象的语言&#xff0c;而C语言则不支持面向对象编程。C提供了类、对象、封装、继承、多态等面向对象的特性&#xff0c;使得程序结构更加清晰、可读性更强。2、模板&#xff1a;C提供了模板的特性&#xff0c;使得程序员可以通…...

【力扣-141】 环形链表 + 【力扣-142】 环形链表 II

&#x1f58a;作者 : Djx_hmbb &#x1f4d8;专栏 : 数据结构 &#x1f606;今日分享 : 霍桑效应(霍索恩效应) : 是指那些意识到自己正在被别人观察的个人具有改变自己行为的倾向。 霍桑效应告诉我们&#xff1a;从旁人的角度&#xff0c;善意的谎言和夸奖真的可以造就一个人&a…...

云计算:优势与未来趋势

文章目录 前言一、云计算的优势1. 降低IT成本2. 提高工作效率3. 提高业务的可靠性和稳定性4. 提升安全性 二、未来发展趋势1. AI与云计算的融合2. 边缘计算的发展3. 多云的趋势4. 服务器和存储的创新 三、 行业应用案例1.金融行业2.医疗保健行业3.教育行业4.零售和物流行业 四、…...

Linux namespace

​ 前言 从《initrd&init进程》可知&#xff0c;我们通过ssh连接linux服务器&#xff0c;其实主是linux启动一shell进程与我们做交互。而Linux又是多租户的&#xff0c;这使用得用户与用户间产生了&#xff0c;资源的争抢。 如何隔离资源&#xff0c;且让用户都无法察觉&…...

第十三章 移动和旋转(上)

移动和旋转是游戏对象最频繁地操作。我们上个章节简单介绍了Cube的移动和旋转。移动是修改transform的position属性&#xff0c;旋转是修改transform的eulerAngles&#xff08;欧拉角&#xff09;属性&#xff0c;两者属性值均可以使用Vector3向量来实现。需要大家注意的是&…...

视频文件切片

1.为什么网络点播系统使用m3u8更有优势?为何点播要用M3U8来搞&#xff1f;存成一个文件不更好吗&#xff1f; 一个MP4文件可能几百M或几个G&#xff0c;如果读取整个MP4文件的信息并且需要下载一段内容&#xff0c;首次打开播放超慢&#xff08;加载时间长&#xff09;。如果把…...

维生素的缺乏与生理功能,是否需要补充维生素【持续学习】

health & nutrition 学习自河南大学丁勇老师&#xff1a;https://space.bilibili.com/510028707 去医院查体内维生素缺啥&#xff1a;营养科或内科开单子 直接门诊查个维生素就可以。9项不到600块 正常吃饭&#xff0c;保湿和防晒 伤口愈合慢——蛋白质&#xff0c;vc 干燥…...

CUDA下载,以及下载GPU版本的pytorch

一、下载anaconda 因为这步我之前就下好了&#xff0c;主要参考这个链接&#xff1a;史上最全最详细的Anaconda安装教程 二、下载CUDA 1.首先观察自己需要什么版本的CUDA&#xff0c;以及是否安装过CUDA 先cmd&#xff0c;输入命令 nvidia-smi结果如下&#xff0c;所以我们…...

学习笔记:c存储类

✨博文作者&#xff1a;烟雨孤舟 &#x1f496; 喜欢的可以 点赞 收藏 关注哦~~ ✍️ 作者简介: 一个热爱大数据的学习者 文章目录 目录 文章目录 简介 auto 存储类 register 存储类 static 存储类 extern 存储类 总结 简介 存储类定义 C 程序中变量/函数的的存储位置…...

236. 二叉树的最近公共祖先【190】

难度等级&#xff1a;中等 上一篇算法&#xff1a; 103. 二叉树的锯齿形层序遍历【191】 力扣此题地址&#xff1a; 236. 二叉树的最近公共祖先 - 力扣&#xff08;Leetcode&#xff09; 1.题目&#xff1a;236. 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点…...