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

🧑‍💻作者:猫十二懿

🏡账号:CSDN 、个人博客 、Github

🎊公众号:猫十二懿

观察者模式

1、观察者模式介绍

观察者模式是一种行为型设计模式,也被称为发布-订阅模式,它定义了一种一对多的依赖关系,当一个对象状态发生改变时,其所有的依赖对象都会得到通知并自动更新。也就是说让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

1.1 观察者模式结构图

在这里插入图片描述

  1. Subject类,可翻译为主题或抽象通知者,一般用一个抽象类或者一个接口实现。它把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
  2. Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫作更新接口。抽象观察者一般用一个抽象类或者一个接口实现。更新接口通常包含一个update()更新方法。
  3. ConcreteSubject类,叫作具体主题或具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
  4. ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。具体观察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。

抽象例子如下:

Subject类:

/*** @author Shier* CreateTime 2023/4/26 22:48* 抽象通知者类*/
public abstract class Subject {protected String subjectState;public String getSubjectState() {return subjectState;}public void setSubjectState(String subjectState) {this.subjectState = subjectState;}private ArrayList<Observer> list = new ArrayList<Observer>();/*** 增加观察者** @param observer*/public void attach(Observer observer) {list.add(observer);}/*** 减少观察者** @param observer*/public void detach(Observer observer) {list.remove(observer);}/*** 通知观察者*/public void notifyObserver() {for (Observer observer : list) {observer.update();}}
}

Observer类:

/*** @author Shier* CreateTime 2023/4/26 22:49* 抽象观察者*/
public abstract class Observer {public abstract void update();
}

ConcreteObserver类:

/*** @author Shier* CreateTime 2023/4/26 22:55*/
public class ConcreteObserver extends Observer{private String name;private Subject subject;public ConcreteObserver(String name, Subject subject) {this.name = name;this.subject = subject;}@Overridepublic void update() {System.out.println("观察者"+this.name+"的最新状态是"+this.subject.subjectState);}
}

ConcreteSubject类:

/*** @author Shier* CreateTime 2023/4/26 22:54* 具体通知者*/
public class ConcreteSubject extends Subject {// 具体的通知方法
}

测试类:

/*** @author Shier* CreateTime 2023/4/26 22:57*/
public class ObserverTest {public static void main(String[] args) {Subject subject = new ConcreteSubject();subject.attach(new ConcreteObserver("shier1", subject));subject.attach(new ConcreteObserver("shier2", subject));subject.attach(new ConcreteObserver("shier3", subject));subject.attach(new ConcreteObserver("shier4", subject));subject.setSubjectState("睡觉了");// 通知其他观察者subject.notifyObserver();}
}

测试结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yZOg9QDW-1685960128875)(…/…/…/…/AppData/Roaming/Typora/typora-user-images/image-20230426230307411.png)]

tSubjectState(“睡觉了”);
// 通知其他观察者
subject.notifyObserver();
}
}

## 2、观察者模式具体例子> 假设我们有一个电商平台,用户可以在该平台上购买商品。在这个场景下,我们可以使用观察者模式来实现购物车功能首先,我们需要定义两个角色:主题(Subject)和观察者(Observer)。主题就是购物车,而观察者就是用户。```java
// 主题接口
interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}// 观察者接口
interface Observer {void update(String itemName);
}
// 购物车类作为主题实现Subject接口
class ShoppingCart implements Subject {private List<Observer> observers = new ArrayList<>();private List<String> items = new ArrayList<>();public void addItem(String itemName) {items.add(itemName);notifyObservers();}public void removeItem(String itemName) {items.remove(itemName);notifyObservers();}@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(items.get(items.size() - 1));}}
}
// 用户类作为观察者实现Observer接口
class User implements Observer {private String name;public User(String name) {this.name = name;}@Overridepublic void update(String itemName) {System.out.println(name + " 收到通知:购物车中添加了商品 " + itemName);}
}
// 测试代码
public class ObserverPatternExample {public static void main(String[] args) {ShoppingCart cart = new ShoppingCart();User user1 = new User("Alice");User user2 = new User("Bob");cart.registerObserver(user1);cart.registerObserver(user2);cart.addItem("手机");cart.addItem("电视");cart.removeItem("手机");}
}

在上面的示例中,购物车(ShoppingCart)作为主题实现了Subject接口。它维护了一个观察者列表,并提供了注册、移除和通知观察者的方法。

用户(User)作为观察者实现了Observer接口。每当购物车的状态发生改变时,购物车会通知所有注册的观察者,观察者接收到通知后可以执行相应的操作。

在测试代码中,我们创建了一个购物车对象(cart),以及两个用户对象(user1和user2)。首先,我们将两个用户注册为购物车的观察者。然后,我们通过调用addItem方法向购物车中添加商品,购物车会通知所有观察者。观察者收到通知后会打印相应的信息。最后,我们通过调用removeItem方法从购物车中移除商品,购物车再次通知观察者。

3、观察者模式总结

观察者模式的优点:

  1. 解耦性:观察者模式可以将观察者和主题对象解耦。主题对象只知道观察者的接口,而不需要知道具体观察者的实现。这使得主题对象和观察者可以独立地进行修改和扩展,互不影响。
  2. 可扩展性:通过添加新的观察者,可以方便地扩展系统的功能。新的观察者可以在不修改现有代码的情况下加入到系统中。
  3. 面向对象设计的灵活性:观察者模式符合面向对象设计的原则,可以实现低耦合、高内聚的设计。

观察者模式的缺点:

  1. 如果观察者过多或者观察者的处理逻辑复杂,会导致通知过程的效率降低。
  2. 观察者模式可能会导致循环引用的问题。当观察者和主题对象相互引用时,需要注意处理引用关系,避免出现内存泄漏的情况。

观察者模式适用于以下场景:

  1. 当一个对象的改变需要同时通知多个其他对象时,可以使用观察者模式。例如,当一个数据模型改变时,需要通知多个视图进行更新。
  2. 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,而且这两个方面都需要独立地改变和扩展时,可以使用观察者模式。例如,一个股票市场的模型中,股票价格的变化会影响到显示股票价格的数字和显示股票价格的图形等多个视图。
  3. 当一个对象的改变需要触发其他多个对象的更新操作时,可以使用观察者模式。例如,一个订单对象状态的改变需要触发库存管理、支付系统、通知系统等多个模块的更新。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【虹科案例】虹科数字化仪在激光雷达大气研究中的应用

01 莱布尼茨研究所使用激光雷达进行大气研究 图 1&#xff1a;在 Khlungsborn 的 IAP 办公室测试各种激光器 大气研究使用脉冲激光束通过测量大气中 100 公里高度的多普勒频移和反向散射光来测量沿光束的温度和风速。返回的光信号非常微弱&#xff0c;会被阳光阻挡&#xff0c…

XML入库后空白字符丢失问题

最近项目上在做电子病历&#xff0c;使用的是第三方的电子病历组件&#xff0c;该病历组件是利用XML来组织数据的。界面上渲染出来的效果如下图&#xff1a; XML渲染后的界面 对应的后台数据&#xff08;已做简化处理&#xff09;是如下XML格式的&#xff0c;其中的空格部分是…

前端入门学习

封装axios axios的基础使用 axios基础使用方法&#xff1a; axios.create({config}) //创建axios实例 axios.get(url,{config}) //get请求 axios.post(url, data,{config}) //post请求 axios.interceptors.request.use() // 请求拦截器 axios.interce…

赛尔号什么时候支持html5,赛尔号:这几只精灵必须拥有!无关强度,只因经典情怀!...

赛尔号这款游戏有着比较老的资历&#xff0c;很多玩家从还是小学生的时候就开始玩起了这个游戏&#xff0c;然后便一直玩到大学&#xff0c;甚至毕业工作。因此&#xff0c;赛尔号不仅仅是一款简单的网页游戏&#xff0c;更是一款充满了情怀的游戏。 那么&#xff0c;接下来的小…

赛尔号星球大战服务器维修,赛尔号星球大战11月29日更新公告

赛尔号星球大战11月29日新增了什么玩法&#xff1f;服务器的维护时间是多少&#xff1f;来看看9k9k小编rayxx带来的赛尔号星球大战11月29日更新公告。 11月29号下午15点至17点更新公告: 1、精灵 新增了两种精灵:亚兰洛(火系)&#xff0c;星吉拉(普通系)。 通过有缘人进行精灵繁…

4399知名游戏-赛尔号图鉴的爬取

4399知名游戏-赛尔号图鉴的爬取 面向对象&#xff1a; 1.疫情居家无聊之人 2.python略懂一点点就行 头文件引入&#xff1a; 如果没有下面的头文件不要慌&#xff0c;打开你的python终端pip install 包名即可 from bs4 import BeautifulSoup import requests import json …

容器技术 — Cgroups 与 Namespaces 支撑实现的操作系统虚拟化

目录 文章目录 目录操作系统虚拟化&#xff08;容器技术&#xff09;的发展历程ChrootCgroupsCgroup SubsystemsCgroup FilesystemCgroup HierarchyCgroups 的操作规则Cgroups 的代码实现 NamespacesUTS namespacePID namespaceIPC namespaceMount namespaceNetwork namespaceU…

使用geoserver发布shp和tiff数据

一、安装并启动geoserver服务 1.1 下载geoserver 进入官网下载 由于geoserver是使用Java语言开发的&#xff0c;所以运行需要java的环境&#xff0c;不同geoserver的版本号对java的版本要求不同&#xff0c;所以选择版本时需注意对应java的版本要求&#xff0c;由于我本地安…

javascript回到顶部

如图&#xff1a; 数字从1到100&#xff0c;滚动后点击章鱼哥便可以回到顶部。 HTML内容不多只有一个a标签内容有一个图片和100个h1标签&#xff0c;但要看清楚是给它设置好了id的&#xff0c;当然不设置id也行但有时候对小白不太友好。 为了使点击图片更加贴合整个页面所以需要…

一段简单的网页返回顶部和返回底部代码(html+css+jquery)

最近用到了返回顶部和底部功能&#xff0c;找了找&#xff0c;查了查&#xff0c;改了改&#xff0c;最终实现效果大概这样子。 以下是相关代码&#xff1a; html部分&#xff1a; <div id"backtotop" class"backtotop"><div class"bt-box…

网页回到顶部的js代码实现

背景 还是给老板写他的个人主页&#xff0c;用到了一个小功能&#xff0c;随手记录下 代码 控制样式的 css 代码如下 /* 回到顶部实现代码的css */ .back-to-top {display: none;/* 默认是隐藏的&#xff0c;这样在第一屏才不显示 */position: fixed;/* 位置是固定的 */bott…

HTML5 回到顶部

图片&#xff1a; html <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>回到顶部</title><link rel"stylesheet" type"text/css" href"css/try.css" /><script src"j…

JS返回顶部代码

2019独角兽企业重金招聘Python工程师标准>>> <!-- 回到顶部 --> <div><span style"font-size:14px"><p id"back-to-top"><a href"#top"><span><img src"public/images/top.jpg" ti…

URL 地址栏能玩出什么新花样?这位歪果程序员小哥给你开开脑洞!

前言 在现在一些互联网营销号的传播素材中&#xff0c;程序员往往会被塑造成一个邋遢、木讷、秃头、低情商的形象&#xff0c;以借此博得普通群众的眼球&#xff0c;吸引他人注意力。 前阵子&#xff0c;暴走漫画发布的一个视频《创造1024》&#xff0c;里面便有多个情节涉及到…

用Python让蔡徐坤在我的命令行里打篮球!| 附完整代码

作者自称是一个经常逛 B 站的肥宅。最近B站上流行的视频素材除了“换脸”&#xff0c;其次就要属“蔡xx打球”视频了。有模仿的、对比的、手绘的... ...更过分的是&#xff0c;竟然有人在命令行输出了他的打球视频。不过&#xff0c;视频中的动画好像是用某个软件生成的 txt 文…

一行代码“黑”掉任意网站

文章目录 只需一行代码&#xff0c;轻轻一点就可以把任意网站变成暗黑模式。 首先我们先做一个实验&#xff0c;在任意网站中&#xff0c;打开浏览器开发者工具(F12)&#xff0c;在 C1onsole 控制台输入如下代码并回车&#xff1a; document.documentElement.style.filterinv…

用Python让蔡徐坤在我的命令行里打篮球!|附完整代码

点击上方↑↑↑蓝字关注我们~ 「2019 Python开发者日」全日程揭晓&#xff0c;请扫码咨询 ↑↑↑ 来源 | 01二进制&#xff08;ID:gh_d1999add1857&#xff09; 编辑 | Jane 【导语】作者自称是一个经常逛 B 站的肥宅。最近 B 站上流行的视频素材除了“换脸”&#xff0c;其次就…

自动化测试,B、C接口要将A接口返回的参数作为入参,有哪些方法?

在进行自动化测试时&#xff0c;如果需要将A接口返回的参数作为B、C接口的入参&#xff0c;可以通过以下几种方法实现&#xff1a; 如果你想学习自动化测试&#xff0c;我这边给你推荐一套视频&#xff0c;这个视频可以说是B站百万播放全网第一的自动化测试教程&#xff0c;同…

直播带货APP小程序系统开发功能有哪些?

直播带货APP小程序系统开发功能有哪些&#xff1f; 1、直播带货&#xff1a;主播一边带货一边直播间活跃气氛&#xff0c;直观地了解产品&#xff0c;下单的概率会更高。还集有观看、打赏、购物、分享于一体。 2、短视频带货&#xff1a;短视频种草&#xff0c;利…

KCNScrew for Mac(mac序列号工具)

KCNScrew for Mac是一款序列号工具&#xff0c;是一款十分简单好用的序列号查找工具。该软件的数据每个月都会更新&#xff0c;包含将近上千款软件的序列号提供给大家。如果你还在苦恼于软件因为没有序列号而不能正常使用到话&#xff0c;想要查看软件序列号的朋友欢迎&#xf…