【设计模式--行为型--观察者模式】

设计模式--行为型--观察者模式

    • 观察者模式
      • 定义
      • 结构
      • 案例
      • 优缺点
      • 使用场景
      • JDK中提供的实现
      • 例:警察抓小偷

观察者模式

定义

又被成为发布订阅模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有的观察者对象,使他们能够自动更新自己。

结构

  • 抽象主题(抽象被观察者 Subject):抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
  • 具体主题(具体被观察者 ConcreteSubject):该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生状态时,给所有注册过的观察者发送通知。
  • 抽象观察者(Observer):是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
  • 具体观察者(Concrete Observer):具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

案例

在这里插入图片描述

/*** 抽象观察者类*/
public interface Observer {void update(String message);
}
/*** 具体观察者角色类*/
public class WeiXinUser implements Observer{private String name;public WeiXinUser(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + "-" + message);}
}
/*** 抽象主题类*/
public interface Subject {// 添加订阅者void attach(Observer observer);// 删除订阅者void detach(Observer observer);// 通知订阅者更新消息void notify(String message);
}
/*** 具体主题类*/
public class SubscriptionSubject implements Subject{// 定义一个集合用来存储多个观察者对象private List<Observer> userList = new ArrayList<>();@Overridepublic void attach(Observer observer) {userList.add(observer);}@Overridepublic void detach(Observer observer) {userList.remove(observer);}@Overridepublic void notify(String message) {for (Observer observer : userList) {observer.update(message);}}
}
public class Test01 {public static void main(String[] args) {// 创建公众号对象SubscriptionSubject subject = new SubscriptionSubject();// 订阅公众号subject.attach(new WeiXinUser("张三"));subject.attach(new WeiXinUser("李四"));subject.attach(new WeiXinUser("老王"));// 公众号更新,发出消息给订阅者(观察者)subject.notify("更新了新的消息");}
}

在这里插入图片描述

优缺点

  • 优点
    • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
    • 被观察者发送通知,所有注册的观察者都会收到消息,可以实现广播机制
  • 缺点
    • 如果观察者非常多,那么所有观察者收到被观察者发送的通知会耗时
    • 如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环通知,会导致系统崩溃

使用场景

  • 对象间存在一对多关系,一个对象的状态发生改变会影响其它对象。
  • 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面时。

JDK中提供的实现

在Java中,通过java.util.Observable类和java.util.Observer接口定义了观察者模式,只要实现它们的子类就可以编写观察者模式。

  • Observable类是抽象目标类(被观察者),它有一个Vector集合成员变量,用于保存所有要通知的观察者对象,有三个重要的方法:
    • void addObserver(Observer o)方法:用于将新的观察者对象添加到集合中。
    • void notifyObserver(Object arg)方法:调用集合中的所有观察者对象的update方法,通知它们数据发生改变。通常越晚加入集合的观察者越先得到通知。
    • void setChange()方法:用来设置一个boolean类型的内部标志,注明目标对象发生了变化,当它为true时,notifyObserver()才会通知观察者。
  • Observer接口
    • observer接口是抽象观察者,它监视目标对象的变化,当目标对象发生变化时,观察者得到通知,并调用update方法,进行相应的工作

例:警察抓小偷

小偷是一个被观察者,所以需要继承Observable类

public class Thief extends Observable {private String name;public Thief(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void steal(){System.out.println("小偷:我偷东西啦!!");super.setChanged();  // changed = truesuper.notifyObservers();}
}

警察是观察者,所以要实现Observer接口

public class Policemen implements Observer {private String name;public Policemen(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic void update(Observable o, Object arg) {System.out.println("警察:" + ((Thief) o).getName() + "我已经发现你了");}
}
public class Test02 {public static void main(String[] args) {// 创建小偷对象Thief thief = new Thief("张三");// 创建警察对象Policemen policemen = new Policemen("李四");// 警察盯着小偷thief.addObserver(policemen);// 小偷偷东西thief.steal();}
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/226081.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

INFINI Labs 产品更新 | Easysearch 新增快照搜索功能,Console 支持 OpenSearch 存储

INFINI Labs 产品又更新啦~&#xff0c;包括 Easysearch v1.7.0、Console v1.13.0。本次各产品更新了 Easysearch 快照搜索功能&#xff1b;Console 支持 OpenSearch 集群存储系统数据、优化了初始化安装向导流程等。 以下是本次更新的详细说明。 INFINI Easysearch v1.7.0 …

遥感论文 | ISPRS | 图神经网络也能做城市街道功能感知?纯视觉方案,效果可观!

论文题目&#xff1a;Knowledge and topology: A two layer spatially dependent graph neural networks to identify urban functions with time-series street view image论文网址&#xff1a;https://www.sciencedirect.com/science/article/pii/S0924271623000680论文代码&…

【lesson16】进程控制之进程替换(1)

文章目录 进程替换是什么&#xff1f;进程替换怎么用&#xff1f;不创建子进程时使用 进程替换是什么&#xff1f; 我们知道fork()之后&#xff0c;父子进程各自执行父进程的一部分代码&#xff0c;如果子进程就想执行一个全新的程序呢&#xff1f; 以前&#xff1a;父子代码…

K8S(二)—介绍

K8S的整体结构图 k8s对象 在 Kubernetes 系统中&#xff0c;Kubernetes 对象是持久化的实体。 Kubernetes 使用这些实体去表示整个集群的状态。 具体而言&#xff0c;它们描述了如下信息&#xff1a; 哪些容器化应用正在运行&#xff08;以及在哪些节点上运行&#xff09;可…

微服务实战系列之ZooKeeper(中)

前言 昨日博主的第一篇ZooKeeper&#xff0c;对它自身具备的能力做了初步介绍。书接上文&#xff0c;马不停蹄&#xff0c;我们继续挖掘它内在的美&#xff0c;充分把握它的核心与脉络。 揭秘ZooKeeper Q&#xff1a;集群一致性协同是如何进行的 我们讲到分布式&#xff0c;…

Renyi散度:Renyi divergence

有关Renyi散度的基本介绍挺多博客已经写了。本文章主要介绍最基础的概念&#xff0c;以及近些年论文中为啥老喜欢引用这个概念。 一.基础概念 Renyi散度主要是描述两个分布之间的关系。对一个离散的概率分布X&#xff0c;其定义域记作&#xff0c;其实就是概率不为零的点的集…

React脚手架搭建

React脚手架 脚手架&#xff1a;可以快速构建项目的基本架构。 脚手架安装命令 可全局安装脚手架 创建项目 来到当前目录下 create-react-app 项目名&#xff08;不要大写字母&#xff09; 运行项目 进到项目里&#xff0c;在项目目录下&#xff0c;执行 npm start &#xff…

C语言-Makefile

Makefile 什么是make&#xff1f; make 是个命令&#xff0c;是个可执行程序&#xff0c;用来解析 Makefile 文件的命令这个命令存放在 /usr/bin/ 什么是 makefile? makefile 是个文件&#xff0c;这个文件中描述了我们程序的编译规则咱们执行 make 命令的时候&#xff0c; m…

华为数通——路由冗余和备份

注&#xff1a;当一条路由的出接口down时&#xff0c;该路由会自动失效。 要求&#xff1a;数据优先走千兆链路。 R1 [ ]ip route-static 172.16.1.0 24 12.1.1.2 目的地址 掩码 下一条 [ ]ip route-static 172.16.1.0 24 21.1.1.2 preference 50 目的地址 …

OxLint 发布了,Eslint 何去何从?

由于最近的rust在前端领域的崛起&#xff0c;基于rust的前端生态链遭到rust底层重构&#xff0c;最近又爆出OxLint&#xff0c;是一款基于Rust的linter工具Oxlint在国外前端圈引起热烈讨论&#xff0c;很多大佬给出了高度评价&#xff1b;你或许不知道OxLint&#xff0c;相比ES…

MySQL 8.x temp空间不足问题

目录 一、系统环境 二、问题报错 三、问题回顾 四、解决问题 一、系统环境 系统Ubuntu20.04 数据库版本MySQL 8.0.21 二、问题报错 在MySQL上执行一个大的SQL查询报错Error writing file /tmp/MYfd142 (OS errno 28 - No space left on device) Exception in thread …

【深度学习】强化学习(六)基于值函数的学习方法

文章目录 一、强化学习问题1、交互的对象2、强化学习的基本要素3、策略&#xff08;Policy&#xff09;4、马尔可夫决策过程5、强化学习的目标函数6、值函数7、深度强化学习 二、基于值函数的学习方法 一、强化学习问题 强化学习的基本任务是通过智能体与环境的交互学习一个策略…

el-date-picker 选择一个或多个日期

el-date-picker可选择多个日期 type“dates” 加个s即可 <div><span>el-date-picker选择多个日期</span><el-date-pickertype"dates"v-model"dateList"placeholder"选择一个或多个日期"></el-date-picker></di…

MyBatis环境的搭建

1.创建 Maven 工程 打开idea新建一个项目File → Project Structure → Project&#xff0c;build system中选择maven &#xff08;1&#xff09;由于 IDEA 中集成了 Maven&#xff0c;所以我们就不需要下载了&#xff0c;直接使用 IDEA 默认的 Maven 进行项目构建。 &#…

【NSX-T】10. 搭建NSX-T环境 —— 使用 BGP 配置 Tier-0 网关

目录 10.1 创建上行链路网段10.2 创建 Tier-0 网关&#xff08;1&#xff09;设置 Interface 信息&#xff08;2&#xff09;设置 BGP添加 BGP 邻居 &#xff08;3&#xff09;设置 BGP 路由重分发设置路由重新分发 10.3 连接 Tier-0 和 Tier-1 网关10.4 使用网络拓扑验证 Tier…

VLAN间的通讯---三层交换

一.三层交换 1.概念 使用三层交换技术实现VLAN间通信 三层交换二层交换 三层转发 2.基于CEF的MLS CEF是一种基于拓补转发的模型 转发信息库&#xff08;FIB&#xff09;临接关系表 转发信息库&#xff08;FIB&#xff09;可以理解为路由表 邻接关系表可以理解为MAC地址表…

Facebook广告系统结构

Facebook广告系统是一个复杂的大型系统&#xff0c;由多个组件和子系统相互配合工作&#xff0c;实现了广告的投放、拍卖、个性化推荐和效果评估等功能。下面小编讲讲Facebook广告系统的结构。 1、广告管理界面 广告管理界面是广告主与Facebook进行交互的入口&#xff0c;广告…

猿人学19题(原比赛平台)

这道题给我搞得有点懵了&#xff0c;我现在还没发现他到底要考察什么&#xff0c;这边我直接协商我的sessionid请求是直接就成功的。&#x1f602; 依旧是分析请求方式&#xff0c;抓包到返回数据的位置 现在可以知道这些数据是ajax返回的&#xff0c;请求的参数是page&#x…

Spark RDD、DataFrame、DataSet比较

在Spark的学习当中&#xff0c;RDD、DataFrame、DataSet可以说都是需要着重理解的专业名词概念。尤其是在涉及到数据结构的部分&#xff0c;理解清楚这三者的共性与区别&#xff0c;非常有必要。 RDD&#xff0c;作为Spark的核心数据抽象&#xff0c;是Spark当中不可或缺的存在…

C语言写的 mini版的 http 服务器 , 很详细

文章目录 效果展示整体架构流程技术细节完整代码 效果展示 例如&#xff1a;htpp://192.168.23.140/home.html -> 正确的请求格式 home.html 这个资源是放在我们服务器里面的 , 并不是随便访问的资源,当然我们可以放很多的资源进去. 整体架构流程 整个实现的流…