(十 八)趣学设计模式 之 观察者模式!

在这里插入图片描述

目录

    • 一、 啥是观察者模式?
    • 二、 为什么要用观察者模式?
    • 三、 观察者模式的实现方式
    • 四、 观察者模式的优缺点
    • 五、 观察者模式的应用场景
    • 六、 总结

🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!
🌟了解状态模式请看: (十 七)趣学设计模式 之 状态模式!
✨更多请看个人主页: 码熔burning

这篇文章带你详细认识一下设计模式中的观察者模式

一、 啥是观察者模式?

想象一下,你订阅了一个你喜欢的博主的博客 ✍️。 只要博主发布了新的文章,你就会立刻收到通知 🔔。 观察者模式就像是这种订阅机制,当一个对象(博主)的状态发生改变时,所有依赖于它的对象(订阅者)都会收到通知并自动更新。

观察者模式,就是定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象的状态发生改变时,会通知所有观察者对象,使它们能够自动更新 🎁。

简单来说,就是让多个“粉丝”时刻关注着“偶像”,一旦“偶像”有啥动静,“粉丝”们立刻知道!

  • 一个对象的状态改变需要通知多个其他对象: 就像博主发布新文章需要通知所有订阅者 📢!
  • 对象之间的依赖关系应该是松耦合的: 就像订阅者可以随时取消订阅,而不会影响博主的正常运作 🤝!
  • 你需要实现发布-订阅(Publish-Subscribe)模式: 就像博主发布文章,订阅者接收通知 📰!

二、 为什么要用观察者模式?

用观察者模式,好处多多 👍:

  • 解耦主题和观察者: 主题对象不需要知道观察者对象的具体类型,只需要知道它们实现了观察者接口 🤝!
  • 支持广播通信: 主题对象可以同时通知多个观察者对象 📣!
  • 动态添加和删除观察者: 可以方便地添加和删除观察者对象,而无需修改主题对象的代码 ➕➖!
  • 提高代码的可维护性和可扩展性: 将主题和观察者的逻辑分离,使得代码更加清晰易懂 💡!

三、 观察者模式的实现方式

观察者模式主要包含两个核心概念:

  • 主题(Subject): 也称为可观察对象,维护一个观察者列表,并提供添加、删除和通知观察者的方法 🏠!
  • 观察者(Observer): 定义了一个更新接口,当主题对象的状态发生改变时,会调用这个接口来通知观察者 ⚙️!
// 观察者接口:订阅者

public interface Observer {
    void update(String message); // 更新消息
}

// 具体观察者:用户

public class User implements Observer {

    private String name;

    public User(String name) {
        this.name = name;
    }

    @Override
    public void update(String message) {
        System.out.println(name + " 收到消息: " + message);
    }
}

// 主题接口:公众号

public interface Subject {
    void registerObserver(Observer observer); // 注册观察者
    void removeObserver(Observer observer); // 移除观察者
    void notifyObservers(String message); // 通知观察者
}

// 具体主题:微信公众号

public class WeChatOfficialAccount implements Subject {

    private List<Observer> observers = new ArrayList<>();
    private String message;

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

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

    @Override
    public void notifyObservers(String message) {
        this.message = message;
        for (Observer observer : observers) {
            observer.update(message);
        }
    }

    public void publishMessage(String message) {
        System.out.println("公众号发布消息: " + message);
        notifyObservers(message);
    }
}

// 客户端

public class Client {
    public static void main(String[] args) {
        // 创建公众号
        WeChatOfficialAccount officialAccount = new WeChatOfficialAccount();

        // 创建用户
        User user1 = new User("张三");
        User user2 = new User("李四");
        User user3 = new User("王五");

        // 注册用户
        officialAccount.registerObserver(user1);
        officialAccount.registerObserver(user2);
        officialAccount.registerObserver(user3);

        // 发布消息
        officialAccount.publishMessage("今天发布了一篇新文章!");

        // 移除用户
        officialAccount.removeObserver(user2);

        // 再次发布消息
        officialAccount.publishMessage("明天要举办一个活动!");
    }
}

代码解释

  • Observer 接口是观察者接口,定义了 update 方法,用于接收主题对象发送的通知。
  • User 类是具体观察者,实现了 Observer 接口,负责处理接收到的通知。
  • Subject 接口是主题接口,定义了 registerObserverremoveObservernotifyObservers 方法,用于管理观察者列表和发送通知。
  • WeChatOfficialAccount 类是具体主题,实现了 Subject 接口,负责维护观察者列表和发送通知。

输出结果

公众号发布消息: 今天发布了一篇新文章!
张三 收到消息: 今天发布了一篇新文章!
李四 收到消息: 今天发布了一篇新文章!
王五 收到消息: 今天发布了一篇新文章!
公众号发布消息: 明天要举办一个活动!
张三 收到消息: 明天要举办一个活动!
王五 收到消息: 明天要举办一个活动!

四、 观察者模式的优缺点

优点:

  • 解耦主题和观察者 🤝!
  • 支持广播通信 📣!
  • 动态添加和删除观察者 ➕➖!
  • 提高代码的可维护性和可扩展性 💡!

缺点:

  • 如果观察者过多,通知会消耗大量资源 😫!
  • 观察者之间可能存在循环依赖,导致系统崩溃 🤯!
  • 难以保证通知的可靠性,如果某个观察者处理通知失败,可能会影响其他观察者 😞!

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

  • GUI 事件处理: 按钮点击、鼠标移动等等 🖱️!
  • 消息队列: 发布-订阅模式 📨!
  • 股票行情: 股票价格变化通知 📈!
  • 天气预报: 天气变化通知 ☀️🌧️!

六、 总结

  • 观察者模式就像“偶像”和“粉丝”,一旦“偶像”有啥动静,“粉丝”们立刻知道! 🤩
  • 核心概念包括主题和观察者! 🔑
  • 优点是解耦主题和观察者、支持广播通信、动态添加和删除观察者、提高代码的可维护性和可扩展性! 👍
  • 缺点是如果观察者过多,通知会消耗大量资源、观察者之间可能存在循环依赖、难以保证通知的可靠性! 👎
  • 适用于一个对象的状态改变需要通知多个其他对象,并且对象之间的依赖关系应该是松耦合的场景! 🎯

希望这篇文章能让你彻底理解观察者模式! 💯 祝你学习愉快! 😄
看完请看:(十 九)趣学设计模式 之 中介者模式!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux虚拟机网络配置-桥接网络配置

简介 本文档旨在指导用户如何在虚拟环境中配置Linux系统的桥接网络&#xff0c;以实现虚拟机与物理主机以及外部网络的直接通信。桥接网络允许虚拟机如同一台独立的物理机一样直接连接到物理网络&#xff0c;从而可以被分配一个独立的IP地址&#xff0c;并能够与网络中的其他设…

视频教育网站开源系统的部署安装 (roncoo-education)服务器为ubuntu22.04.05

一、说明 前端技术体系&#xff1a;Vue3 Nuxt3 Vite5 Vue-Router Element-Plus Pinia Axios 后端技术体系&#xff1a;Spring Cloud Alibaba2021 MySQL8 Nacos Seata Mybatis Druid redis 后端系统&#xff1a;roncoo-education&#xff08;核心框架&#xff1a;S…

线程相关八股

1. 线程和进程的区别&#xff1f; 进程&#xff1a;进程可以简单理解为进行一个程序&#xff0c;比如说我们打开一个浏览器&#xff0c;打开一个文本&#xff0c;这就是开启了一个进程&#xff0c;一个进程想要在计算机中运行&#xff0c;需要将程序交给CPU&#xff0c;将数据…

Python 绘制迷宫游戏,自带最优解路线

1、需要安装pygame 2、上下左右移动&#xff0c;空格实现物体所在位置到终点的路线&#xff0c;会有虚线绘制。 import pygame import random import math# 迷宫单元格类 class Cell:def __init__(self, x, y):self.x xself.y yself.walls {top: True, right: True, botto…

【音视频】VLC播放器

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 一、vlc是什么&#xff1f; VLC Media Player&#xff08;简称VLC&#xff09;是一款免费、开源、跨平台的多媒体播放器&#xff0c;由非营利组织VideoLAN开发&#xff0c;最…

vue2+ele-ui实践

前言&#xff1a;真理先于实践&#xff0c;实践发现真理&#xff0c;再实践检验真理 环境&#xff1a;vue2 & element-ui 正片&#xff1a; Select 选择器 简称 下拉框 下拉框完整的使用循环 下拉框 → 点击下拉框 → 展示数据 → 选择数据 → 下拉框显示数据 核心具有…

刷题日记——部分二分算法题目分享

前言 咱们紧跟上一期结合时间复杂度浅谈二分法的好处, 并分享部分二分题目(将持续更新题目,绝对值你一个收藏)-CSDN博客 笔者接着分享一些刷过的关于二分算法的题目. 第一题 1283. 使结果不超过阈值的最小除数 - 力扣&#xff08;LeetCode&#xff09; 这道题就是典型的二…

excel 斜向拆分单元格

右键-合并单元格 右键-设置单元格格式-边框 在设置好分割线后&#xff0c;你可以开始输入文字。 需要注意的是&#xff0c;文字并不会自动分成上下两行。 为了达到你期望的效果&#xff0c;你可以通过 同过左对齐、上对齐 空格键或使用【AltEnter】组合键来调整单元格中内容的…

关于常规模式下运行VScode无法正确执行“pwsh”问题

前言&#xff1a; pwsh在系统环境中正确配置&#xff0c;且可以运行在cmd&#xff0c; powshell&#xff08;5.1&#xff09;--- 都需要在管理员权限下运行 &#xff08;打开setting&#xff09; 打开setting.json &#xff08;在vscode中添加 powershell 7 路径&…

企微审批中MySQL字段TEXT类型被截断的排查与修复实践

在MySQL中&#xff0c;TEXT类型字段常用于存储较大的文本数据&#xff0c;但在一些应用场景中&#xff0c;当文本内容较大时&#xff0c;TEXT类型字段可能无法满足需求&#xff0c;导致数据截断或插入失败。为了避免这种问题&#xff0c;了解不同文本类型&#xff08;如TEXT、M…

异常 PipeMapRed.waitOutputThreads(): subprocess failed with code 127

直接放问题异常 hadoop jar /opt/module/hadoop-3.3.2/share/hadoop/tools/lib/hadoop-streaming-3.3.2.jar \ -D mapreduce.map.memory.mb100 \ -D mapreduce.reduce.memory.mb100 \ -D mapred.map.tasks1 \ -D stream.num.map.output.key.fields2 \ -D num.key.fields.for.pa…

Focal Loss (聚焦损失) :解决类别不平衡与难易样本的利器,让模型学会“重点学习”

1. 为什么需要Focal Loss&#xff1f; 2. 交叉熵损失的问题 3.Focal Loss的智慧&#xff1a;给不同的错误“区别对待” 4.代码演示 1. 为什么需要Focal Loss&#xff1f; 在机器学习和深度学习中&#xff0c;类别不平衡&#xff08;Class Imbalance&#xff09; 是一个普遍…

算法系列之数据结构-二叉树

在计算机科学中&#xff0c;数据结构是组织和存储数据的方式&#xff0c;以便能够高效地访问和修改数据。树&#xff08;Tree&#xff09;是一种非常重要的非线性数据结构&#xff0c;广泛应用于各种算法和应用中。本文将详细介绍树的基本概念、常见类型以及用Java实现树的遍历…

进来了解一下python的深浅拷贝

深浅拷贝是什么&#xff1a;在Python中&#xff0c;理解深拷贝&#xff08;deep copy&#xff09;和浅拷贝&#xff08;shallow copy&#xff09;对于处理复杂的数据结构&#xff0c;如列表、字典或自定义对象&#xff0c;是非常重要的。这两种拷贝方式决定了数据在内存中的复制…

磁盘空间不足|如何安全清理以释放磁盘空间(开源+节流)

背景&#xff1a; 最近往数据库里存的东西有点多&#xff0c;磁盘不够用 查看磁盘使用情况 df -h /dev/sda5&#xff08;根目录 /&#xff09; 已使用 92% 咱们来开源节流 目录 背景&#xff1a; 一、开源 二、节流 1.查找 大于 500MB 的文件&#xff1a; 1. Snap 缓存…

vue3学习-2(深入组件)

vue3学习-2&#xff08;深入组件&#xff09; 1.开始2.基础3.深入组件注册全局注册局部注册组件名格式 PropsProps 声明响应式 Props 解构 3.5将解构的 props 传递到函数中单向数据流更改对象 / 数组类型的 propsProp 校验 事件触发与监听事件事件参数声明触发的事件事件校验 组…

Java 入门 (超级详细)

一、什么是Java Java是一种高级编程语言&#xff0c;由Sun Microsystems公司于1995年推出。Java具有跨平台性、面向对象、健壮性、安全性、可移植性等特点&#xff0c;被广泛应用于企业级应用开发、移动应用开发、大数据处理、云计算等领域。Java程序可以在不同的操作系统上运…

23种设计模式之工厂方法模式(Factory Method Pattern)【设计模式】

文章目录 一、工厂方法模式简介二、关键点三、代码示例3.1 定义抽象产品3.2 实现具体产品3.3 创建抽象工厂3.4 实现具体工厂3.5 客户端代码 四、解释五、优缺点5.1 优点5.2 缺点 六、适用场景 一、工厂方法模式简介 工厂方法模式&#xff08;Factory Method Pattern&#xff0…

io学习----->标准io

思维导图&#xff1a; 一.io的作用 io是实现对文件的操作&#xff0c;把运行结果存到文件中&#xff0c;读取文件的数据&#xff0c;方便后期查询。 二.io的概念 io是指系统 和外部设备或用户之间的数据交互 I:input 表示数据从外部设备输入到内存中&#xff1b; O:output…

从 R1 到 Sonnet 3.7,Reasoning Model 首轮竞赛中有哪些关键信号?

DeepSeek R1 催化了 reasoning model 的竞争&#xff1a;在过去的一个月里&#xff0c;头部 AI labs 已经发布了三个 SOTA reasoning models&#xff1a;OpenAI 的 o3-mini 和deep research&#xff0c; xAI 的 Grok 3 和 Anthropic 的 Claude 3.7 Sonnet。随着头部 Al labs 先…