设计模式之 观察者模式

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象(Subject)。当主题对象的状态发生变化时,所有依赖于它的观察者都会得到通知并自动更新。观察者模式的应用可以减少对象之间的耦合度,促进系统的解耦,使得对象间的协作变得更加灵活。

观察者模式特别适用于那些需要在一个对象状态变化时,通知多个对象并进行相应处理的场景。它通常用于事件驱动的系统、模型-视图-控制(MVC)架构、GUI框架等应用中。

一、观察者模式的定义

在观察者模式中,主题对象(Subject)保持对多个观察者对象(Observer)的引用,并在自身状态改变时通知它们。观察者对象通过订

阅主题对象来接收通知,而无需主动去查询主题对象的状态。主题和观察者之间通过一个简单的接口进行通信,使得它们之间的耦合度降低。

二、观察者模式的组成部分

观察者模式主要由以下几个角色组成:

  1. Subject(主题/被观察者)

    主题对象是观察者模式的核心,它维护一个观察者列表,并定义向观察者发送通知的方法。主题的状态发生变化时,它会通知所有的观察者。
    常见的操作有:注册观察者、删除观察者、通知观察者。
  2. Observer(观察者)

    观察者是需要接收主题通知的对象,它定义了接收通知的接口。当主题对象状态发生变化时,观察者会自动调用该接口来更新自身状态。
  3. ConcreteSubject(具体主题)

    具体主题类实现了Subject接口,并维护自己的状态。当它的状态变化时,会调用所有注册的观察者的更新方法。
  4. ConcreteObserver(具体观察者)

    具体观察者类实现了Observer接口,并在接收到通知时更新自己的状态。具体观察者与具体主题密切相关,通常它们的状态依赖于主题的状态。

三、观察者模式的工作原理

观察者模式的工作原理可以总结为以下步骤:

  1. 注册观察者:观察者对象通过调用主题对象的attach()方法注册自己,成为主题的观察者。

  2. 通知观察者:当主题的状态发生变化时,主题对象调用notify()方法,通知所有注册的观察者。

  3. 观察者更新:观察者对象收到通知后,会调用自身的update()方法,根据主题的状态更新自己的状态。

  4. 取消订阅:如果观察者不再关心主题的状态变化,它可以通过调用主题的detach()方法注销自己,不再接收通知。

四、观察者模式的代码示例

假设我们有一个简单的天气预报系统,系统需要通知不同的显示设备(如手机、电脑)更新天气信息。当天气变化时,所有已注册的显示设备都会自动接收到天气更新。

定义观察者接口
public interface Observer {public void update(String weather);
}
定义主题接口
public interface Subject {void attach(Observer observer);void detach(Observer observer);void notifyObservers();
}
具体主题类:WeatherStation(天气站)
public class WeatherStation implements Subject{private List<Observer> observers = new ArrayList<>();private String weather;public void setWeather(String weather) {this.weather = weather;notifyObservers();}@Overridepublic void attach(Observer observer) {observers.add(observer);}@Overridepublic void detach(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(weather);}}
}
具体观察者类:PhoneDisplay(手机显示)
public class PhoneDisplay implements Observer{@Overridepublic void update(String weather) {System.out.println("手机端天气变为"+ weather);}
}
具体观察者类:ComputerDisplay(电脑显示)
public class ComputerDisplay implements Observer{@Overridepublic void update(String weather) {System.out.println("电脑端天气变为"+weather);}
}
客户端代码
public class Client {public static void main(String[] args) {WeatherStation station = new WeatherStation();station.attach(new ComputerDisplay());station.attach(new PhoneDisplay());station.setWeather("晴天");}
}
运行结果

五、观察者模式的优缺点

优点:
  1. 降低耦合性:观察者模式使得主题和观察者之间的耦合度降低,观察者无需了解主题的内部实现,主题也无需了解每个观察者的具体细节。只通过接口进行通信。

  2. 支持多种观察者:多个观察者可以同时订阅同一个主题对象,在主题对象状态发生变化时,所有观察者都会被通知并做出响应。

  3. 增强灵活性:如果主题的状态发生变化,观察者无需主动查询主题,而是通过通知机制自动获取更新。观察者可以随时添加或移除,不影响系统其他部分。

  4. 扩展性强:如果需要新增新的观察者,只需要创建新的观察者类,并注册到主题中即可,主题对象不需要做任何修改,符合开放封闭原则。

缺点:
  1. 可能引起性能问题:如果观察者非常多,每当主题状态变化时,都会通知所有观察者。如果观察者处理较慢或者状态更新频繁,可能会导致性能问题。

  2. 观察者过多时管理困难:如果观察者的数量非常大,管理这些观察者可能变得复杂,特别是在需要追踪哪些观察者已经收到通知时。

  3. 难以控制通知的顺序:在一些复杂的场景中,可能希望通知观察者的顺序有一定的控制,而观察者模式通常是按照注册顺序发送通知的。

六、观察者模式的应用场景

  1. 事件处理系统:在事件驱动的系统中,事件的发生通常需要通知多个监听者,如图形界面中的按钮点击、鼠标拖拽等事件。

  2. 模型-视图-控制(MVC)模式:在MVC架构中,视图(Observer)需要根据模型(Subject)的变化来更新显示。模型的状态变化会通知所有相关的视图进行刷新。

  3. 通知推送系统:当数据变化时,通知用户的系统,比如邮件通知、即时通讯应用中的消息推送等。

  4. 股票市场监控:投资者或分析师(观察者)订阅股票(主题)信息,当股票价格发生变化时,系统会自动推送通知给所有订阅者。

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

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

相关文章

【python】将word文档内容转换为excel表格

在日常工作中&#xff0c;我们经常需要将Word文档中的内容提取并转换为Excel表格&#xff0c;以便进行数据分析和处理。本文将介绍如何使用Python编写一个简单的程序&#xff0c;将Word文档中的内容转换为Excel表格。 一.实例 使用以下word文档作为例子&#xff1a; 工具界面如…

Linux|进程程序替换

目录 什么是进程替换 替换原理 exec函数 exec* 函数的共性 什么是进程替换 进程程序替换是指将一个进程中正在运行的程序替换为另一个全新的程序的过程&#xff0c;但替换不是创建新进程&#xff0c;只是将对应程序的代码和数据进行替换。具体来说&#xff0c;这个替换过程涉…

大数运算(加减乘除和输入、输出模块)

为什么会有大数呢&#xff1f;因为long long通常为64位范围约为 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807&#xff0c;最多也就19位&#xff0c;那么超过19位的如何计算呢&#xff1f;这就引申出来大数了。 本博客适合思考过这道题&#xff0c;但是没做出来或…

IntelliJ+SpringBoot项目实战(四)--快速上手数据库开发

对于新手学习SpringBoot开发&#xff0c;可能最急迫的事情就是尽快掌握数据库的开发。目前数据库开发主要流行使用Mybatis和Mybatis Plus,不过这2个框架对于新手而言需要一定的时间掌握&#xff0c;如果快速上手数据库开发&#xff0c;可以先按照本文介绍的方式使用JdbcTemplat…

flex布局 昵图网【案例】

效果展示 只是个大概&#xff0c;可自己完善。 昵图网 代码展示 <body><!-- https://static.ntimg.cn/original/images/soso.png --><div class"container"><div class"header"><!-- <div class"logo"><i…

[第五空间 2021]pklovecloud 详细题解

知识点: 构造POP链 PHP类的作用域 NULL强比较 目录穿越 源码如下: <?php include flag.php; class pkshow { function echo_name() { return "Pk very safe^.^"; } } class acp { protected $cinder; public $neutron;public $n…

dockerfile构建Nginx镜像练习二(5-2)

环境准备&#xff1a; (1)保证拥有centos基础镜像 docker images | grep centos (2)服务器保证可以连接外网 1.创建工作目录 mkdir nginx cd nginx 2.在工作目录中创建并编写Dockerfile文件 vim dockerfile #定义基础镜像 FROM centos:7#维护者信息(可缺省) MAINTAINER d…

Android Surfaceflinger显示图层合成方式

Android SurfaceFlinger是Android系统中负责窗口管理和图像合成的核心组件。它接收来自不同应用的图层数据&#xff0c;并将这些图层合并成一个单一的图像&#xff0c;然后输出到显示设备上。SurfaceFlinger的合成方式主要涉及两种&#xff1a;Client合成和Device合成。 adb s…

wsl安装

一. wsl简介 1. wsl和wsl2的区别 wsl需要把linux命令翻译为windows命令&#xff0c;性能差一些。 wsl2直接使用linux内核&#xff0c;不需要翻译&#xff0c;性能好&#xff0c;但开销相对大一点&#xff0c;因为需要多运行一个hyper-v虚拟机 (并非完整的虚拟机&#xff0c;是…

任务通知的本质(任务通知车辆运行) 软件定时器的本质(增加游戏音效)

任务通知的本质 没有任务通知 所谓"任务通知"&#xff0c;你可以反过来读"通知任务"。 我们使用队列、信号量、事件组等等方法时&#xff0c;并不知道对方是谁。使用任务通知时&#xff0c;可 以明确指定&#xff1a;通知哪个任务。 使用队列、信号量、…

Kubernetes的pod控制器

文章目录 一&#xff0c;什么是pod控制器二&#xff0c;pod控制器类型&#xff08;重点&#xff09;1.ReplicaSet2.Deployment3.DaemonSet4.StatefulSet5.Job6.Cronjob 三&#xff0c;pod与控制器的关系1.Deployment2.SatefulSet2.1StatefulSet组成2.2headless的由来2.3有状态服…

【单元测试】【Android】JUnit 4 和 JUnit 5 的差异记录

背景 Jetbrain IDE 支持生成 Test 类&#xff0c;其中选择JUnit5 和 JUnit&#xff0c;但是感觉这不是标准的单元测试&#xff0c;因为接口命名吧。 差异对比 两者生成的单测API名称同原API&#xff0c;没加test前缀的。使用差异主要表现在&#xff1a; setUp &#xff06; …

知识中台在多语言客户中的应用

在全球化的商业环境中&#xff0c;企业面临着多语言客户服务的挑战。HelpLook知识中台作为一种智能化解决方案&#xff0c;为企业提供了一个强大的工具&#xff0c;以实现多语言客户服务的自动化和优化。 一、多语言客户服务的重要性 多语言客户服务对于跨国企业至关重要&…

使用 Elastic AI Assistant for Search 和 Azure OpenAI 实现从 0 到 60 的转变

作者&#xff1a;来自 Elastic Greg Crist Elasticsearch 推出了一项新功能&#xff1a;Elastic AI Assistant for Search。你可以将其视为 Elasticsearch 和 Kibana 开发人员的内置指南&#xff0c;旨在回答问题、引导你了解功能并让你的生活更轻松。在 Microsoft AI Services…

【K8S问题系列 |18 】如何解决 imagePullSecrets配置正确,但docker pull仍然失败问题

如果 imagePullSecrets 配置正确&#xff0c;但在执行 docker pull 命令时仍然失败&#xff0c;可能存在以下几种原因。以下是详细的排查步骤和解决方案。 1. 检查 Docker 登录凭证 确保你使用的是与 imagePullSecrets 中相同的凭证进行 Docker 登录&#xff1a; 1.1 直接登录…

Redis的特性ubuntu进行安装

文章目录 1.六大特性1.1内存存储数据1.2可编程1.3可扩展1.4持久化1.5集群1.6高可用1.7速度快 2.具体应用场景&#xff08;了解&#xff09;3.Ubuntu安装Redis3.1安装指令3.2查看状态3.3查找配置文件3.4修改文件内容3.5重启服务器生效3.6安装客户端并进行检查 4.Redis客户端介绍…

【ASE】第八课_冰(ice)的效果

今天我们一起来学习ASE插件&#xff0c;希望各位点个关注&#xff0c;一起跟随我的步伐 今天我们来学习一个简单的冰的效果&#xff0c;这个是根据油管上的视频制作的 可在我的资源里下载模型&#xff0c;贴图&#xff0c;材质 思路 1.物体表面结冰的效果&#xff0c;也就是…

回溯法基础入门解析

回溯法 前 言 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。回溯是递归的副产品&#xff0c;只要有递归就会有回溯。回溯法&#xff0c;一般可以解决如下几种问题&#xff1a; 组合问题&#xff1a;N个数里面按一定规则找出k个数的集合切割问题&#xff1a;一…

Redis原理及应用

Redis简介 Redis是开源的&#xff08;BSD许可&#xff09;&#xff0c;数据结构存储于内存中&#xff0c;被用来作为数据库&#xff0c;缓存和消息代理。它支持多种数据结构&#xff0c;例如&#xff1a;字符串&#xff08;string&#xff09;&#xff0c;哈希&#xff08;hash…

Ubuntu ESP32开发环境搭建

文章目录 ESP32开发环境搭建安装ESP-IDF搭建一个最小工程现象 ESP32开发环境搭建 最近有个小项目需要用到能够联网的mcu驱动&#xff0c;准备玩玩esp的芯片&#xff0c;记录下ESP32开发环境搭建的过程。 ESP-IDF 是乐鑫科技为其 ESP32 系列芯片提供的官方开发框架。这个框架主…