设计模式之-观察者模式,快速掌握观察者模式,通俗易懂的讲解观察者模式以及它的使用场景

文章目录

  • 一、快速理解观察者模式
  • 二、观察者模式适用场景
  • 三、观察者模式优缺点
    • 观察者模式的优点包括:
    • 观察者模式的缺点包括:
  • 四、代码示例
  • 五、我们来听一个故事,加深理解


一、快速理解观察者模式

当谈到设计模式中的观察者模式(Observer Pattern)时,它是一种行为型设计模式,用于在对象之间建立一种一对多的依赖关系,当一个对象的状态发生改变时,它的所有依赖者都会得到通知并自动更新。

通俗地说,观察者模式就像是一个主题(被观察者)和一群订阅者(观察者)之间的关系。主题维护一个订阅者列表,当主题状态发生变化时,它会通知所有的订阅者进行相应的更新操作。

二、观察者模式适用场景

  1. 当一个对象的改变需要同时改变其他对象,并且你不知道有多少对象需要改变时。
  2. 当一个对象需要将自己的改变通知给其他对象,而又不希望与其紧密耦合时。

三、观察者模式优缺点

观察者模式的优点包括:

  • 解耦:观察者模式将主题和观察者解耦,使它们可以独立变化,互不影响。
  • 扩展性:可以灵活地添加新的观察者,或者改变观察者的行为,而无需修改主题的代码。
  • 维护一致性:主题和观察者之间建立了一种松散的依赖关系,保证了一致性。

观察者模式的缺点包括:

  • 过多的通知:当主题对象有大量的观察者时,每次状态变化都需要通知所有观察者,可能会造成性能问题。
  • 循环引用:当观察者之间相互引用时,可能导致循环引用的问题,需要注意避免。

总结来说,观察者模式适用于需要实现对象间的动态一对多关系,并且希望避免紧耦合的场景。它可以帮助我们实现松散耦合的设计,提高代码的可维护性和扩展性。

四、代码示例

面是一个简单的示例代码来说明观察者模式的实现:

import java.util.ArrayList;
import java.util.List;// 主题接口
interface Subject {void attach(Observer observer); // 添加观察者void detach(Observer observer); // 移除观察者void notifyObservers(); // 通知观察者
}// 具体主题类
class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();private int state;public void attach(Observer observer) {observers.add(observer);}public void detach(Observer observer) {observers.remove(observer);}public void notifyObservers() {for (Observer observer : observers) {observer.update();}}public int getState() {return state;}public void setState(int state) {this.state = state;notifyObservers(); // 状态变化时通知观察者}
}// 观察者接口
interface Observer {void update();
}// 具体观察者类
class ConcreteObserver implements Observer {private ConcreteSubject subject;public ConcreteObserver(ConcreteSubject subject) {this.subject = subject;subject.attach(this); // 注册观察者}public void update() {int state = subject.getState();// 执行相应的操作System.out.println("观察者收到通知,当前状态为:" + state);}
}// 示例代码
public class ObserverPatternExample {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();ConcreteObserver observer1 = new ConcreteObserver(subject);ConcreteObserver observer2 = new ConcreteObserver(subject);subject.setState(1);subject.setState(2);}
}

在上述示例中,主题(ConcreteSubject)维护了一个观察者列表,并提供了添加、移除和通知观察者的方法。观察者(ConcreteObserver)实现了观察者接口,并在构造函数中将自身注册到主题中。当主题状态发生变化时,它会遍历观察者列表,并调用每个观察者的 update() 方法来进行相应的操作。

五、我们来听一个故事,加深理解

假设有一个小镇,这个小镇上有一家天气预报中心。每天早上,天气预报中心会发布当天的天气情况,包括温度、湿度、风力等信息。同时,小镇上的几个居民对天气情况非常关注,因为天气会影响他们的日常生活。

在这个故事中,天气预报中心是被观察者(主题),而居民们是观察者。他们想要根据天气情况来做出相应的安排,比如选择穿什么衣服、是否要带伞等。

现在,我们来看一下如何使用观察者模式来实现这个故事。

首先,我们需要定义一个主题(WeatherCenter)接口,其中包含了添加观察者、移除观察者和通知观察者的方法。

interface WeatherCenter {void addObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}

然后,我们定义一个具体的天气预报中心(ConcreteWeatherCenter)类,实现了主题接口,并维护了一个观察者列表。

class ConcreteWeatherCenter implements WeatherCenter {private List<Observer> observers = new ArrayList<>();private WeatherData weatherData;public void addObserver(Observer observer) {observers.add(observer);}public void removeObserver(Observer observer) {observers.remove(observer);}public void notifyObservers() {for (Observer observer : observers) {observer.update(weatherData);}}public void setWeatherData(WeatherData weatherData) {this.weatherData = weatherData;notifyObservers();}
}

接下来,我们定义一个观察者(Resident)接口,其中包含了更新方法。

interface Observer {void update(WeatherData weatherData);
}

然后,我们定义一个具体的居民(ConcreteResident)类,实现了观察者接口。

class ConcreteResident implements Observer {private String name;public ConcreteResident(String name) {this.name = name;}public void update(WeatherData weatherData) {// 根据天气情况做出相应的安排System.out.println(name + "收到天气预报,今天的温度是:" + weatherData.getTemperature() + "℃");}
}

最后,我们来看一下如何将这些角色组合起来并运行起来。

public class ObserverPatternStory {public static void main(String[] args) {ConcreteWeatherCenter weatherCenter = new ConcreteWeatherCenter();ConcreteResident resident1 = new ConcreteResident("John");weatherCenter.addObserver(resident1);ConcreteResident resident2 = new ConcreteResident("Alice");weatherCenter.addObserver(resident2);WeatherData weatherData = new WeatherData(25); // 假设温度为25℃weatherCenter.setWeatherData(weatherData);}
}

在这个故事中,天气预报中心是主题,居民们是观察者。当天气预报中心发布天气信息时,所有的居民都会收到通知,并根据天气情况做出相应的安排。

这个故事中的观察者模式展示了一个实际生活中常见的场景。通过观察者模式,天气预报中心和居民之间建立了一种松散的依赖关系,使得天气预报中心能够方便地通知居民们最新的天气情况,居民们也能够根据天气情况做出适当的调整。

故事中的观察者模式的优点是:

天气预报中心和居民之间实现了解耦,它们可以独立变化,互不影响。
天气预报中心可以方便地添加或移除观察者,居民们也可以灵活地订阅或取消订阅天气通知。
天气预报中心发布天气信息时,所有的居民都能够及时收到通知,确保信息的一致性。
观察者模式的缺点在这个故事中并不明显,但在实际应用中可能存在以下问题:

如果观察者过多或者观察者执行的操作较为耗时,可能会导致性能问题。
观察者之间相互引用时,可能出现循环引用的问题,需要注意避免。
总结来说,观察者模式在实际应用中非常有用,可以帮助我们实现对象之间的一对多关系,实现解耦、灵活性和一致性。无论是天气预报、事件通知还是其他需要实现观察者和被观察者之间关系的场景,观察者模式都是一个强大的工具。

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

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

相关文章

视觉学习(7) —— 接收数据和发送数据以及全局变量和浮点数

1、前提 创建一个四个字节的地址 2、发送数据 &#xff08;1&#xff09;直接发送数据 再观察地址里的值 与我们想要值不一样 输入0&#xff0c;而实际值则为 结论&#xff1a;直接输入值到地址&#xff0c;值会发生变化 &#xff08;2&#xff09;走全局变量发送数据 添加全…

系列十(实战)、发送 接收批量消息(Java操作RocketMQ)

一、发送 & 接收批量消息 1.1、概述 批量消息是指RocketMQ可以把一组消息集合一次性发送&#xff0c;这一组消息会被当做一个消息供消费者消费。 1.2、Demo05MQTestApp /*** Author : 一叶浮萍归大海* Date: 2023/12/25 11:48* Description: 发送 & 接收批量消息*/ …

基于SSM实现的电动汽车充电网点管理系统

一、系统架构 前端&#xff1a;jsp | jquery | bootstrap | css 后端&#xff1a;spring | springmvc | jdbc 环境&#xff1a;jdk1.8 | mysql 二、代码及数据库 三、功能介绍 01. web端-首页 02. web端-登录 03. web端-注册 04. web端-我要充电 05. web端-个人中心-消…

搞定Apache Superset

踩雷了无数次终于解决了Superset的一系列问题 现在是北京时间2023年12月27日&#xff0c;亲测有效。 Superset概述 Apache Superset是一个现代的数据探索和可视化平台。它功能强大且十分易用&#xff0c;可对接各种数据源&#xff0c;包括很多现代的大数据分析引擎&#xff…

php5.6安装mongo扩展

需要依赖 可以参考 php5.6安装openssl扩展 https://pecl.php.net/package/mongo 安装mongo扩展 wget https://pecl.php.net/get/mongo-1.6.16.tgz/Users/hina/Applications/php/5.6.40/bin/phpize./configure --with-php-config/Users/hina/Applications/php/5.6.40/bin/ph…

JS深浅拷贝

区分 B复制了A的值&#xff0c;如果A被修改&#xff0c;B的值也被改变&#xff0c;那就是浅拷贝。 如果B的值没有跟着修改&#xff0c;那就是深拷贝 深浅拷贝的方式 1、遍历赋值 2、Object.create() 3、JSON.parse()和JSON.stringify() 浅拷贝-遍历 let a {name:"…

recognize-anything 识别万物

docker run --gpus all -itd --nametest -v /app:/app nvcr.io/nvidia/cuda:11.8.0-devel-ubuntu22.04 ###########安装过程######################## # 更新包索引 apt update # 安装 Python 3 apt install python3 -y # 安装 pip apt install python3-pip -y # 安装…

k8s面试之——简述网络模型

kubernetes网络模型是kubernetes集群中管理容器网络通信的一种机制&#xff0c;用于实现pod间、pod与外部网络间的通信和互联&#xff0c;并提供了多种网络插件和配置选项来满足不同应用场景下的需求。kubernetes网络模型可以分为一下几个部分&#xff1a; 1. pod网络模型 在…

详解结构体(包含结构体内存对齐,柔性数组,位段)【尊嘟很详细】

​ 结构体 结构体是一些值的集合&#xff0c;这些值称为成员变量&#xff0c;结构的成员可以是标量、数组、指针,甚至是其他结构体。 成员名可以与程序中其它变量同名&#xff0c;互不干扰。 结构体的定义 &#xff08;struct结构名{}&#xff09; struct books {int a;c…

饮用水除溴酸盐和硝酸盐中的应用与优势

随着人们对健康和生活质量的日益关注&#xff0c;饮用水安全问题成为了社会关注的焦点。在自然水体中&#xff0c;溴酸盐和硝酸盐的含量往往较高&#xff0c;而这些物质对人体健康存在一定的潜在风险。因此&#xff0c;饮用水处理中如何有效去除溴酸盐和硝酸盐&#xff0c;成为…

TypeScript下载安装,编译运行

TypeScript是拥有类型的JavaScript超集&#xff0c;它可以编译成普通、干净、完整的JavaScript代码。 简单理解&#xff1a;TypeScript就是加强版的JavaScript。 TypeScript最终会被编译成JavaScript代码&#xff0c;那么我们必然需要对应的编译环境 环境搭建前提&#xff1a…

【扩散模型】7、GLIDE | 文本指引的图像生成和编辑

论文&#xff1a;GLIDE: Towards Photorealistic Image Generation and Editing with Text-Guided Diffusion Models 代码&#xff1a;https://link.zhihu.com/?targethttps%3A//github.com/openai/glide-text2im 出处&#xff1a;OpenAI 一、背景 在扩散模型经过了一系列…

【51单片机系列】DS1302时钟模块

本文是关于DS1302时钟芯片的相关介绍。 文章目录 一、 DS1302时钟芯片介绍二、DS1302的使用2.1、DS1302的控制寄存器2.2、DS1302的日历/时钟寄存器2.3、片内RAM2.4、DS1302的读写时序 三、SPI总线介绍四、DS1302使用示例 一、 DS1302时钟芯片介绍 DS1302是DALLAS公司推出的涓流…

GitLab 删除或移动项目

首先明说&#xff0c;删除后无法恢复 第一步&#xff1a;找到要删除的项目 第二步&#xff1a;进入目录后&#xff0c;左侧菜单&#xff0c;设置 >>> 通用&#xff0c;拉到最下面找到“高级”&#xff0c;点击右侧“展开” 第三步&#xff1a;点击“展开”后往下拉&a…

CSS 文字弹跳效果

鼠标移过去 会加快速度 <template><div class"bounce"><p class"text" :style"{animationDuration: animationDuration}">欢迎使用UniApp Vue3&#xff01;</p></div> </template><script> export d…

ArcGIS渔网的多种用法

在ArcGIS中有一个渔网工具&#xff0c;顾名思义&#xff0c;可以用来创建包含由矩形像元所组成网络的要素类。不太起眼&#xff0c;但它的用途却有很多&#xff0c;今天跟大家分享一篇关于渔网的多种用途。 1.马赛克地图制作 2.基于网格的设施密度统计制作马赛克地图 准备材…

牙齿敏感困扰?试试清九野小红盾牙膏

随着冬季的来临&#xff0c;许多人可能会面临牙齿敏感的问题。在这个时候&#xff0c;食用冷饮都会让牙齿感到非常酸痛。一般来说&#xff0c;不良的饮食习惯和不正确的刷牙方式&#xff0c;都会导致牙齿敏感&#xff0c;但根本还是牙本质小管的暴露和空洞&#xff0c;需要修复…

家校互通小程序实战开发02首页搭建

目录 1 创建应用2 搭建首页总结 我们上一篇介绍了家校互通小程序的需求&#xff0c;创建了对应的数据源。有了这个基础的分析之后&#xff0c;我们就可以进入到开发阶段了。开发小程序&#xff0c;先需要创建应用。 1 创建应用 登录控制台&#xff0c;点击创建应用&#xff0c…

[c]统计数字

题目描述 某次科研调查时得到了n个自然数&#xff0c;每个数均不超过1500000000&#xff08;1.5*109&#xff09;。已知不相同的数不超过10000个&#xff0c;现在需要统计这些自然数各自出现的次数&#xff0c;并按照自然数从小到大的顺序输出统计结果。 输入描述: 第1行是整数…

Linux阶段性项目——FTP服务器

一、FTP服务概述 ​FTP为File Transfer Protocol的缩写&#xff0c;即文件传输协议&#xff0c;是TCP/IP 协议族中的协议之一。FTP是一个用于在计算机网络上在客户端和服务器之间进行文件传输的应用层协议。RFC 959定义了FTP协议规范。是互联网上使用的最广泛的文件传输协议&a…