设计模式-观察者模式(观察者模式的需求衍变过程详解,关于监听的理解)

news2025/1/20 10:52:31

目录

  • 前言
    • 概念
    • 你有过这样的问题吗?
  • 详细介绍
    • 原理:
    • 应用场景:
  • 实现方式:
    • 类图
    • 代码
  • 问题回答
    • 监听,为什么叫监听,具体代码是哪
    • 观察者模式的需求衍变过程
    • 观察者是为什么是行为型
  • 总结:

前言

    在软件设计中,对象之间的通信是非常常见的情况。然而,当对象之间的通信过于紧密,可能会导致代码的耦合度增加,使得系统难以维护和扩展。为了解决这个问题,观察者模式应运而生。本文将介绍观察者模式的原理、应用场景以及实现方式,并通过图、代码和例子进行详细说明。

概念

    观察者模式通过定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,会自动通知所有观察者对象进行相应的更新操作。

你有过这样的问题吗?

  • 概念中说“多个观察者对象同时监听某一个主题对象”,什么叫监听,监听是被动的还是主动的?在代码中哪块体现监听了?
  • 观察者模式的需求是如何演变的?
  • 观察者模式属于行为型,为什么呢?行为型有什么特点吗?
  • 观察者模式应用场景有哪些?有什么不足吗?

带着类似的问题,看下面的内容,文章的最后也会对这些问题一一回答

详细介绍

原理:

    观察者模式由两个核心角色组成:主题(Subject)和观察者(Observer)。主题对象维护一个观察者列表(有个容器用来放观察者),当主题对象的状态发生变化时,会遍历观察者列表,依次通知每个观察者进行相应的更新操作。观察者对象则通过注册到主题对象上,以接收主题对象的通知。

应用场景:

观察者模式在许多实际应用中都有广泛的应用,例如:

  1. 消息订阅和发布系统:主题对象充当消息发布者,观察者对象充当消息订阅者。当发布者发布新消息时,订阅者会收到通知并进行相应的处理。

  2. GUI开发:主题对象可以是用户界面组件,观察者对象可以是与该组件相关的其他组件。当用户界面组件发生变化时,其他组件可以及时更新自身的状态。

  3. 股票市场监控系统:主题对象可以是股票市场,观察者对象可以是投资者。当股票市场行情发生变化时,投资者可以及时了解到最新的行情。

实现方式:

类图

在这里插入图片描述

代码

下面通过一个简单的示例来演示观察者模式的实现。

  1. 首先,我们定义主题接口(Subject),包含注册观察者、移除观察者和通知观察者的方法。
public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}
  1. 然后,我们定义观察者接口(Observer),包含接收通知并进行更新操作的方法。
public interface Observer {
    void update();
}
  1. 接下来,我们实现具体的主题类(ConcreteSubject),并在该类中实现注册观察者、移除观察者和通知观察者的方法。
public class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    
    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }
    
    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
    
    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
    
    // 其他业务逻辑...
}
  1. 最后,我们实现具体的观察者类(ConcreteObserver),并在该类中实现接收通知并进行更新操作的方法。
public class ConcreteObserver implements Observer {
    @Override
    public void update() {
        // 执行更新操作...
    }
}

    通过以上代码,我们可以看到,主题对象和观察者对象之间并没有直接的耦合关系,它们通过接口进行通信,实现了松耦合的对象间通信。

问题回答

监听,为什么叫监听,具体代码是哪

    在观察者模式中,观察者对象通过注册(或订阅)的方式来监听某一个主题对象。这个监听的过程在代码中体现在观察者对象注册到主题对象的观察者列表中。

    具体地,主题对象通常会提供一些方法,例如attach(observer)和detach(observer),用于观察者对象的注册和注销。当主题对象的状态发生变化时,它会遍历观察者列表,并调用每个观察者对象的相应方法,通知它们状态的变化。

    关于为什么称之为"监听",这是因为在观察者模式中,观察者对象并不需要主动去轮询或查询主题对象的状态,而是被动地接收主题对象的通知。观察者对象通过注册到主题对象上,就像是在"监听"主题对象的状态变化。

    观察者对象并没有主动去听的动作,但它们被动地接收主题对象的通知,从而实现了对主题对象状态变化的监听。这种被动的接收通知的行为,可以理解为观察者对象在"监听"主题对象。

观察者模式的需求衍变过程

故事背景:

    老板回来,前台秘书发通知消息给正在玩的同事们(前提是,同事提前在秘书那“注册”过–“老板来了通知我一下”),收到秘书的通知后,同事们各自采取行动

宏观

    最初的通知者和观察者是明确知道对方的存在的,但是在经过一次次的优化后观察者和通知者都不知道对方具体存在只知晓一个接口或者抽象类,这里就是在一对多通知的时候使用这种抽象的好处,不需要知道具体的通知者和观察者。

微观:

1.双向耦合:
    开始有三个类:前台秘书类,看股票同事类,客户端,此时的前台秘书类与观察者类相互耦合,前台秘书类要增加观察者、观察者需要前台的的状态。
需要解决的问题是:前台秘书类与观察者类相互耦合。

2.解耦
    增加抽象的观察者,增加了看NBA的同事,看股票的同事与看NBA 的同事继承抽象观察者。前台秘书类中与具体的观察者耦合的地方都改成了抽象观察者。存在的问题是:具体的观察者不应该依赖具体的主题,而是需要一个抽象的通知者。如果前台有事来不及通知,那么通知谁来做?前台不想通知某位同事,需要有移除方法进行支持。

3.观察者模式
    观察者模式的作用是在解耦合,让耦合的双方都依赖抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
如果观察者是风马牛不相及的类,使用接口更加合适。

观察者模式的不足:
    抽象通知者依赖抽象观察者,应该由客户端决定通知谁;并不是每个具体的观察者都是更新方法。

事件与委托的实现
    看股票的观察者类、看NBA 观察者类 去掉了父类抽象观察者,并将更新方法名改为自己合适的方法名字。抽象观察者不要了,声明EventHandler委托,在具体的统治者类增加委托事件-update。

观察者是为什么是行为型

    观察者模式是一种行为型设计模式,因为它关注的是对象之间的行为和交互,通过定义接口和松耦合的方式实现了对象之间的动态关联。

    在观察者模式中,被观察者和观察者之间通过定义接口进行通信,这就意味着它们之间可以有不同的行为。被观察者负责维护观察者的列表,并在状态发生改变时通知观察者。观察者则负责定义在接收到通知时要执行的行为。

    观察者模式的行为型特点还体现在它的实现方式上。在观察者模式中,被观察者和观察者之间是松耦合的,它们之间的关联是动态的,可以随时添加或移除观察者。这种灵活性使得观察者模式非常适合在复杂的系统中处理对象之间的行为和交互。

    简单一句话总结行为型设计模式特点:
    行为型模式的核心,都有一个类,把整个模式要做的事封装在这个类的一个方法里执行。
    具体在观察者模式中这个类是ConcreteObserver,具体是其中的构造方法。具体观察者,只管要它要订阅哪个主题,(this.subject=subject.)但是它不管订阅的主题具体做什么事,进而实现了整个设计模式要实现的行为。

总结:

    观察者模式通过定义一种一对多的依赖关系,实现了对象之间的松耦合通信。它能够帮助我们构建可维护和可扩展的系统。在实际应用中,我们可以根据具体的需求进行灵活的扩展和定制。希望本文对你理解观察者模式有所帮助。

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

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

相关文章

变道超车?中国首架电动垂直起降飞行器即将首飞,载人是亮点

根据御风未来的官方消息&#xff0c;他们的首架全国产电动垂直起降飞行器Matrix 1已经顺利完成了各项地面测试&#xff0c;并且即将迎来首次试飞。这款飞行器采用纯电能源&#xff0c;不需要跑道即可起降&#xff0c;并且具备智能化全自主飞行能力&#xff0c;无需飞行驾驶员操…

C++--红黑树

1.什么是红黑树 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路径会比其他路径长出俩倍&#xff0c;因…

java.net.BindException Address already in use: NET_Bind解决

java.net.BindException Address already in use: NET_Bind 两种解决方法 两种解决方法 (1) kill 占用此端口的线程 查看报错的端口 netstat -ano | findstr 16825tasklist | findstr 1092 如果占用的程序不重要直接kill taskkill /f /pid 16825 (2) 修改启动端口 找一个没…

系统架构设计师-信息安全技术(2)

目录 一、安全架构概述 1、信息安全所面临的威胁 二、安全模型 1、安全模型的分类 2、BLP模型 3、Biba 模型 4、Chinese Wall模型 三、信息安全整体架构设计 1、WPDRRC模型 2、各模型的安全防范功能 四、网络安全体系架构设计 1、开放系统互联安全体系结构 2、安全服务与安…

typedef

t y p e d e f typedef typedef 声明&#xff0c;简称typedef&#xff0c;是创建现有类型的新名字。 比如&#xff1a; #include <bits/stdc.h> using namespace std; typedef long long ll; int main() {ll n;scanf("%lld",&n);printf("%lld"…

共定位数据和环境准备

共定位数据和环境准备 一、数据准备 如果需要做eqtl-GWAS的共定位&#xff0c;则需要按照药靶教程中&#xff0c;将eqtl数据放在smr目录内 如果是纯GWAS-GWAS的共定位&#xff0c;涉及到本地数据的&#xff0c;需要将其整理成模板SNP的格式&#xff0c;并且需要chr&#xff0c…

CASAIM与哈尔滨工业大学达成航空航天关键零部件自动化智能测量系统合作,助力航空航天特种复合新材料性能分析

近期&#xff0c;CASAIM与哈尔滨工业大学在航空航天关键零部件自动化智能测量系统展开全面合作&#xff0c;为后续进行航空航天特种复合新材料性能分析提供可靠的试验数据。 哈尔滨工业大学是隶属于工业和信息化部的全国重点大学&#xff0c;是国家“985工程”“211工程”“双…

【Ubuntu】从Graylog到Grafana Loki:构建更强大的网络设备管理和监控系统

在将Graylog部署到生产环境时&#xff0c;我们遇到了一些问题&#xff0c;其中最主要的是无法安装MongoDB并且无法随时重启机器去修改BIOS设置来修复问题 【WARNING: MongoDB 5.0 requires a CPU with AVX support, and your current system does not appear to have that! 】。…

云服务 Ubuntu 20.04 版本 使用 Nginx 配置SSL证书和nginx从HTTP跳转到HTTPS

1.云服务申请免费的SSL证书 2.从云服务SSL证书下载到本地解压上传到服务器 3.配置Nginx下的 nginx.cof 文件 4.开放安全组&#xff0c;内部与外部 5.测试配置与跳转是否成功 1.云服务申请免费的SSL证书 1.1.登录云平台找到SSL证书 注意&#xff1a;博主这里是腾讯云&#x…

程序员如何利用公网远程访问查询本地硬盘【内网穿透】

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《高效编程技巧》《cpolar》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 公网远程访问本地硬盘文件【内网穿透】 文章目录 公网远程访问本地硬盘文件【内网穿透】前言1. 下载cpolar和Everything软件1.…

OJ练习第151题——克隆图

克隆图 力扣链接&#xff1a;133. 克隆图 题目描述 给你无向 连通 图中一个节点的引用&#xff0c;请你返回该图的 深拷贝&#xff08;克隆&#xff09;。 示例 分析 对于一张图而言&#xff0c;它的深拷贝即构建一张与原图结构&#xff0c;值均一样的图&#xff0c;但是…

光伏发电系统的并网接入点选择及接入方案

1.并网方式及接入点选择 (1))并网点与接入点定义 1)并网点。对于有升压站的分布式电源&#xff0c;并网点为分布式电源升压站中压侧母线或节点&#xff0c;对于无升压站的分布式电源&#xff0c;并网点为分布式电源的输出汇总点。图1中所示A1、B1点分别为分布式电源A、B的并网…

工业视觉相机镜头选型方法

一、相机选型 1、首先&#xff0c;根据检测需求确定选用黑白/彩色、面阵/线阵相机&#xff0c;接口类型一般选择GigE 2、确定检测精度要求&#xff08;最小特征尺寸mm&#xff09;、视野范围&#xff0c;一个测量精度对应几个像素数&#xff08;一般取3-5&#xff09; 3、计…

【山河送书第七期】:《强化学习:原理与Python实战》揭秘大模型核心技术RLHF!

《强化学习&#xff1a;原理与Python实战》揭秘大模型核心技术RLHF&#xff01; 一图书简介二RLHF是什么&#xff1f;三RLHF适用于哪些任务&#xff1f;四RLHF和其他构造奖励模型的方法相比有何优劣&#xff1f;五什么样的人类反馈才是好反馈&#xff1f;六如何减小人类反馈带来…

Matplotlib数据可视化(四)

1.在绘图中显示公式 在Matplotlib中可以使用LaTex的命令来编辑公式&#xff0c;只需要在字符串前面加一个r即可。 示例1&#xff1a; import numpy as np import matplotlib.pyplot as plt plt.xlim([1,4]) plt.ylim([1,3]) plt.text(2,2,r$ \alpha \beta \pi \lambda \omeg…

新榜 | CityWalk本地生活商业价值洞察报告

如果说现在有人问&#xff0c;最新的网络热词是什么? “CityWalk”&#xff0c;这可能是大多数人的答案。 近段时间&#xff0c;“CityWalk”刷屏了各种社交媒体&#xff0c;给网友们带来了一场“城市漫步”之旅。 脱离群体狂欢&#xff0c;这个在社交媒体引发热议的词汇背后又…

【leetcode】232. 用栈实现队列

1.使用两个栈结构构建队列 我们需要自定义栈及其相关操作 栈结构遵循后入先出的原则&#xff0c;队列结构遵循先入先出的原则 构建具有两个栈结构的队列&#xff0c;栈pushST用于数据的插入&#xff0c;栈popST用于数据的删除 为栈结构动态开辟空间并初始化栈结构 //定义一个具…

object获取的两种方式/Object.keys使用/解构赋值

object获取的两种方式&#xff1a; data() {return {abj: {aa: {A: 1}}}},created() {console.log(this.abj.aa) //第一种console.log(this.abj["aa"]) //第二种}, Object.keys使用/解构赋值&#xff1a; return {footList: [],abj: {aa: {A: 12,AA:22},bb: {…

macOS系统安装python3

官网下载 官网&#xff1a;https://www.python.org/ 选择最新版本下载 双击安装包 点击继续 点击继续 点击同意 点击安装 终端执行 python3 --version

九、Linux下,如何在命令行进入文本编辑页面?

1、文本编辑基础 说到文本编辑页面&#xff0c;那就必须提到vi和vim&#xff0c;两者都是Linux系统中&#xff0c;常用的文本编辑器 2、三种工作模式 3、使用方法 &#xff08;1&#xff09;在进入Linux系统&#xff0c;在输入vim text.txt之后&#xff0c;会进入文本编辑中&…