观察者模式(二十)

news2024/10/6 6:44:14

相信自己,请一定要相信自己

上一章简单介绍了迭代器模式(十九), 如果没有看过, 请观看上一章

一. 观察者模式

引用 菜鸟教程里面 观察者模式介绍: https://www.runoob.com/design-pattern/observer-pattern.html

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。

比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式

一.一 介绍

意图: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

主要解决: 一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用: 一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决: 使用面向对象技术,可以将这种依赖关系弱化。

关键代码: 在抽象类里有一个 ArrayList 存放观察者们。

应用实例: 1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。

优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。

缺点:
1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景:

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

注意事项: 1、JAVA 中已经有了对观察者模式的支持类。 2、避免循环引用。 3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。


组成角色具体关系
抽象观察者角色Observer为所有的具体观察者定义一个接口,在得到主题通知时更新自己
具体观察者角色Baidu, Sina, User实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调
抽象被观察者角色Subject一个抽象主题,它把所有对观察者对象的引用保存在一个集合中
具体被观察者角色WeatherDataSubject一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知

image-20230615184354714

二. 观察者实例

如观察天气的情况

二.一 观察的对象实体 Weather

@Data
@Builder
public class Weather {
    /**
      温度, 气压, 湿度
     */
    private float temperature;
    private float pressure;
    private float humidity;
}

二.二 抽象观察者 Observer

public interface Observer {

    public void update (Weather weather);
}

二.三 具体观察者实现

二.三.一 百度网站

@Slf4j
public class BaiDu implements Observer{
    private Weather weather ;
    @Override
    public void update(Weather weather) {
        this.weather = weather;
        display();
    }

    public void display (){
        if (weather == null) {
            return ;
        }
        log.info(">>>>>>>>>>>>>百度网站获取到天气数据,进行个性化操作");
        log.info(">>>温度: {}, 气压: {}, 湿度: {}", weather.getTemperature(),weather.getPressure(),
                weather.getHumidity());
    }

}

二.三.二 新浪网站

@Slf4j
public class Sina implements Observer{
    private Weather weather ;
    @Override
    public void update(Weather weather) {
        this.weather = weather;
        display();
    }

    public void display (){
        if (weather == null) {
            return ;
        }
        log.info(">>>>>>>>>>>>>新浪网站获取到天气数据,进行个性化操作");
        log.info(">>>温度: {}, 气压: {}, 湿度: {}", weather.getTemperature(),weather.getPressure(),
                weather.getHumidity());
    }

}

二.三.三 订阅者

@Slf4j
public class User implements Observer{
    private Weather weather ;
    @Override
    public void update(Weather weather) {
        this.weather = weather;
        display();
    }

    public void display (){
        if (weather == null) {
            return ;
        }
        log.info(">>>>>>>>>>>>>订阅用户获取到天气数据,进行个性化操作");
        log.info(">>>温度: {}, 气压: {}, 湿度: {}", weather.getTemperature(),weather.getPressure(),
                weather.getHumidity());
    }

}

二.四 抽象被观察者 Subject

public interface Subject {
    public void registerObserver(Observer observer);

    public void remove (Observer observer);

    public void notifyObservers();
}

二.五 具体观察者实现

@Slf4j
public class WeatherDataSubject implements Subject{
    private List<Observer> observerList = new ArrayList<>();
    private Weather weather;
    @Override
    public void registerObserver(Observer observer) {
        observerList.add(observer);
    }

    @Override
    public void remove(Observer observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observerList) {
            observer.update(this.weather);
        }
    }

    public void setWeather(Weather weather) {
        this.weather = weather;
        dataChange();
    }

    public void dataChange() {
        // 更新后,数据发生了改变。
        log.info("获取到了最新的数据: {}", this.weather);
        notifyObservers();
    }
}

二.六 客户端调用

  @Test
    public void oneTest() {
        WeatherDataSubject weatherDataSubject = new WeatherDataSubject();
        weatherDataSubject.registerObserver(new BaiDu());
        weatherDataSubject.registerObserver(new Sina());

        // 设置数据
        weatherDataSubject.setWeather(
                Weather.builder()
                        .temperature(35.0f)
                        .pressure(20.0f)
                        .humidity(30.f)
                        .build()
        );
        User user = new User();
        // 再添加个数据
        weatherDataSubject.registerObserver(user);

        weatherDataSubject.setWeather(
                Weather.builder()
                        .temperature(30.0f)
                        .pressure(21.0f)
                        .humidity(32.f)
                        .build()
        );


        weatherDataSubject.remove(user);


        weatherDataSubject.setWeather(
                Weather.builder()
                        .temperature(32.0f)
                        .pressure(22.0f)
                        .humidity(33.f)
                        .build()
        );

    }

image-20230615185146367

三. Java 实现观察者模式

Java 语言, 可以通过 Observer(Observer) Observable(Subject) 实现观察者处理

三.一 具体观察者和抽象观察者

@Slf4j
public class NewUser implements Observer {
    private String name;
    public NewUser(String name) {
        this.name = name;
    }
    @Override
    public void update(Observable o, Object arg) {
        log.info("{} 观察到信息发生了变化 {}", name,arg);
    }
}

三.二 具体被观察者和抽象被观察者

public class NewWeatherDataSubject extends Observable {
    private Weather weather;

    public NewWeatherDataSubject (Weather weather) {
        this.weather = weather;
    }

    public void setWeather(Weather weather) {
        this.weather = weather;
        // 改变了
        super.setChanged();
        super.notifyObservers(weather);
    }
}

三.三 客户端调用

@Test
    public void twoTest() {
        Weather weather = Weather.builder()
                .temperature(32.0f)
                .pressure(22.0f)
                .humidity(33.f)
                .build();
        NewWeatherDataSubject newWeatherDataSubject = new NewWeatherDataSubject(weather);
        newWeatherDataSubject.addObserver(new NewUser("用户1"));
        newWeatherDataSubject.addObserver(new NewUser("用户2"));
        newWeatherDataSubject.addObserver(new NewUser("用户3"));
        log.info("温度发生改变");
        weather.setTemperature(34.f);
        newWeatherDataSubject.setWeather(weather);
        log.info("温度再次发生改变");
        weather.setTemperature(30.f);
        newWeatherDataSubject.setWeather(weather);
    }

image-20230615185508442


本章节的代码放置在 github 上:


https://github.com/yuejianli/DesignPattern/tree/develop/Observer


谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!

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

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

相关文章

cef支持.net6.0

开发环境&#xff1a;vs2022,.net6.0 cef CefSharp.Common.NETCore 114.2.100 安装 Cefsharp简介 CEF &#xff0c;全称Chromium Embedded Framework &#xff0c;基于谷歌 Chromium项目的开源Web Browser控件&#xff0c;它的主要用途是嵌入了第三方应用以实现浏览器相关的功…

【C#】简单认识TransactionScope,以及常见的事务类型

在实际项目开发时&#xff0c;后端编码少不了事务处理。 为什么要用事务&#xff0c;其中一个最直接的原因就是保持数据完整性和一致性 目录 1、C#事务概念1.1、逻辑单元1.2、Transaction对象1.3、事务简单实例 2、事务场景描述3、事务流程图3.1、没有事务流程3.2、有事务流程 …

黑客是怎样练成的?

网学黑客技术的人越来越多了&#xff0c;不少人都不知道该怎么学&#xff0c;今天就来详细的说一说黑客是如何炼成的。 首先&#xff0c;什么是黑客&#xff1f; 黑客 &#xff1a;泛指擅长IT技术的电脑高手 黑客一词&#xff0c;源自英文Hacker&#xff0c;早期其实就是一群…

【MySQL】一文带你了解检索数据

&#x1f3ac; 博客主页&#xff1a;博主链接 &#x1f3a5; 本文由 M malloc 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;LeetCode刷题集&#xff01; &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指…

21 RBM(Restricted Boltzmann Machine)——受限玻尔兹曼机

文章目录 21 RBM(Restricted Boltzmann Machine)——受限玻尔兹曼机21.1 背景介绍22.2 RBM模型表示22.3 Inference问题22.4 Marginal问题 21 RBM(Restricted Boltzmann Machine)——受限玻尔兹曼机 21.1 背景介绍 什么是玻尔兹曼机&#xff1a; 简单来说就是具有条件的Marko…

无线蓝牙耳机排行榜,十大口碑最好蓝牙耳机

近年来&#xff0c;随着生活水平的提高&#xff0c;越来越多的人对高品质蓝牙耳机的需求日益增加。无论我们在选购什么产品&#xff0c;我们都会考虑一个价值范围&#xff0c;买蓝牙耳机也是同样&#xff0c;都会给自己一个预算&#xff0c;然后根据预算去网上搜寻这个价格范围…

【python学习】-读入xlsx文件,将datetime.time转为minute的格式,并将新数据存入csv文件

读入xlsx文件&#xff0c;将datetime.time转为minute的格式&#xff0c;并将新数据存入csv文件 任务概要思路设计代码实现导入相关库时间转换函数算法内核csv文件结果 接到一个需求&#xff0c;师兄在做稳定性测试时&#xff0c;时间显示格式为<class ‘datetime.time’>…

深入剖析 Python 函数参数传递机制及高级应用

前言 在本篇文章中&#xff0c;笔者将带你深入探讨 Python 函数传参的进阶主题。 通过阅读本篇文章&#xff0c;你可以深入了解 Python 函数传参的进阶主题&#xff0c;掌握更多高级的函数技巧&#xff0c;提升你的 Python 编程能力。 前面分享了Python 函数传参基础篇&#xf…

图像生成--对抗生成模型

生成模型概述 对抗生成模型 机器学习中的两大主要问题&#xff1a; 判别生成 判别模型的典型代表即为图像分类任务&#xff0c;即给定一个数据&#xff0c;判定他是哪一类。 判别模型学习到的是一个概率&#xff08;贝叶斯过程&#xff09; 而生成模型的区别在于&#xf…

【Elacticsearch】 原理/数据结构/面试经典问题整理

对Elacticsearch 原理/数据结构/面试经典问题整理的文章&#xff1b; 映射 | Elasticsearch: 权威指南 | Elastic Elacticsearch介绍 Elasticsearch,这里简称ES。ES是一个开源的高可用高扩展的分布式全文搜索与分析引擎&#xff0c;可以提供PB级近实时的数据存储和检索能力&am…

SpringBoot自定义starter入门

一、创建一个普通的Maven项目 pom.xml文件修改 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&quo…

你知道如何将音频转文字吗?

我跟你们说&#xff0c;我认识一名盲人音乐人&#xff0c;他很热爱音乐创作&#xff0c;但是因为听力的限制&#xff0c;无法像其他人那样从录音中获取音乐素材。然而&#xff0c;有一天他听说了一个神奇的功能——音频转文字&#xff0c;这个功能可以将音频文件转换成文字文本…

从技术谈到管理,把系统优化的技术用到企业管理

很多技术人员在职业上对自己要求高&#xff0c;工作勤奋&#xff0c;承担越来越大的责任&#xff0c;最终得到信任&#xff0c;被提拔到管理岗位。但是往往缺乏专业的管理知识&#xff0c;在工作中不能从整体范围优化工作流程&#xff0c;仍然是“个人贡献者”的工作方式&#…

低功耗晶振电路设计

晶振电路设计 晶振中负性阻抗的原理 晶振的回路主要由两部分组成&#xff0c; 一部分是激活分支&#xff0c; 用于提供能量给晶振启动直至达到稳定的相位&#xff0c;另一部分是被动分支&#xff0c; 主要由电阻&#xff0c; 两个外部负载电容以及所有的寄生电容&#xff0c;…

手写RPC总结篇

协议制定&#xff1a;client到server做交互的通信协议&#xff0c;比如request response 网络端点peer 难点1 : Jetty嵌入 ◆jetty Server ◆ServletContextHandler ◆ServletHolder jetty server 起到网络监听的作用ServletContextHandler注册到jetty server中ServletHolde…

测试开发之Python自动化 Pytest 之 fixture

Pytest 之 fixture unittest 和 nose 都支持 fixture 的,但是 fixture 在 pytest 里使用更灵活。也算是 pytest 的一个闪光点吧可以理解为一个跟 setup 和 teardown 这种前后置类似的东西。但是比它们要强大、灵活很多 fixtur 当做参数传入 # -*- coding: utf-8 -*-import p…

图像处理实战02-yolov5目标检测

yolov5 YOLOv5 是一种目标检测算法&#xff0c;它是 YOLO (You Only Look Once) 系列算法的最新版本。YOLOv5 采用了一种新的架构&#xff0c;它包括一个基于 CSPNet (Cross Stage Partial Network) 的主干网络以及一系列改进的技巧&#xff0c;如多尺度训练、数据增强、网络混…

互联网行业-镭速文件传输系统方案

互联网行业是一个快速变化和高度竞争的行业&#xff0c;这一行业需要传输大量的数据、代码和文件。在互联网企业的生产和运营过程中&#xff0c;需要传输各种敏感和大型的文件&#xff0c;例如业务报告、数据分析、软件代码等。这些文件需要在不同的部门、不同的地点之间高效地…

微服务springcloud 07 hystrix + turbine 集群聚合监控

01.hystrix dashboard 一次只能监控一个服务实例&#xff0c;使用 turbine 可以汇集监控信息&#xff0c;将聚合后的信息提供给 hystrix dashboard 来集中展示和监控 02.新建 sp10-turbine 项目 03.pom.xml <?xml version"1.0" encoding"UTF-8"?&…

C语言---malloc(0)会产生什么结果,真的是空指针吗?

前言 &#xff08;1&#xff09;几天前在一个交流群中看到有人说&#xff0c;面试问malloc(0)会怎么样是真的恶心。 &#xff08;2&#xff09;这个突然激起了我的好奇心。居然还可以malloc(0)&#xff1f;&#xff01; &#xff08;3&#xff09;经过测试最后&#xff0c;发现…