设计模式-观察者模式(Observer Pattern)结构|原理|优缺点|场景|示例

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,允许一个或多个观察者对象订阅主题对象,当主题对象状态发生改变时,会通知所有已订阅的观察者对象,使得它们能够自动更新自己。

主要角色:

  1. Subject(抽象主题、被观察者)

    • 提供了一个注册和移除观察者的接口方法(如 registerObserver() 和 removeObserver())。
    • 定义了一个通知所有观察者的接口方法(如 notifyObservers())。
  2. ConcreteSubject(具体主题、具体被观察者)

    • 继承自抽象主题,是抽象主题的具体实现。
    • 维护一个观察者集合,并在自身状态改变时调用 notifyObservers() 方法通知所有观察者。
    • 可能会提供获取当前状态的方法。
  3. Observer(抽象观察者)

    • 定义了一个更新接口,所有具体的观察者都要实现这个接口。
    • 提供了当主题状态变化时需要执行的更新方法(如 update())。
  4. ConcreteObserver(具体观察者)

    • 是Observer接口的具体实现,包含了指向具体主题的引用。
    • 在接收到主题的通知后,通过调用 update() 方法响应状态的变化,更新自身的状态

工作流程:

  1. 观察者通过 registerObserver() 方法注册到被观察者。
  2. 当被观察者状态发生改变时,调用 notifyObservers() 方法。
  3. 被观察者遍历观察者集合,调用每个观察者的 update() 方法。
  4. 观察者在其 update() 方法中根据主题提供的信息或者直接访问主题的状态来进行相应的更新操作。

优缺点:

优点:

  1. 松耦合:观察者模式实现了主题(被观察者)和观察者之间的松耦合。主题不需要知道观察者的具体类型,只需要通过一个通用的接口进行通知,这有助于降低模块间的耦合度,提高系统的灵活性和可维护性。

  2. 扩展性好:增加新的观察者或删除已有的观察者都很方便,只需修改具体的观察者类,对主题和其他观察者没有影响。

  3. 响应式编程友好:观察者模式可以很容易地构建基于事件的系统,使得系统具备事件驱动能力,能够及时响应状态变化。

缺点:

  1. 如果观察者过多,每次主题状态变化时都需要通知所有的观察者,可能会造成效率低下,尤其是在大型系统中,通知机制可能成为瓶颈。

  2. 如果观察者和主题之间存在循环依赖,可能导致系统难以理解和调试。

  3. 如果没有良好的设计,可能会出现观察者忘记取消注册而导致内存泄露的情况。

  4. 当主题类的状态频繁变化时,会导致大量无谓的通知发送,加大系统的负载。

  5. 对于观察者来说,可能会因为不清楚主题的状态何时发生变化,而过度依赖于外部通知,不利于逻辑的清晰性和独立性。

 应用场景:

  • 在GUI编程中,按钮点击事件通知多个组件更新界面。
  • 数据绑定场景,数据模型变化时自动更新视图层。
  • 网络通信,服务器状态改变时通知所有订阅的客户端。
  • 日志框架中,日志级别变更时重新配置所有相关的日志处理器。

代码示例(以Java为例)

// 抽象观察者接口
public interface Observer {
    // 更新方法,当被观察者状态改变时会被调用
    void update(String message);
}

// 抽象被观察者接口
public interface Subject {
    // 注册观察者
    void registerObserver(Observer observer);
    // 移除观察者
    void removeObserver(Observer observer);
    // 通知所有观察者
    void notifyObservers(String message);
}

// 具体被观察者类
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(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }

    // 被观察者的状态发生变化时,触发通知
    public void changeState(String newState) {
        System.out.println("Subject state changed to: " + newState);
        notifyObservers(newState);
    }
}

// 具体观察者类
public class ConcreteObserver implements Observer {
    private String name;

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

    @Override
    public void update(String message) {
        System.out.println(name + " received the following message: " + message);
    }
}

// 测试类
public class Main {
    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();
        
        Observer observer1 = new ConcreteObserver("Observer 1");
        Observer observer2 = new ConcreteObserver("Observer 2");

        subject.registerObserver(observer1);
        subject.registerObserver(observer2);

        subject.changeState("New State");  // 改变被观察者状态,此时会触发通知
    }
}

在这个示例中,ConcreteSubject 类是具体的被观察者,它管理着一个观察者列表。当其状态改变时,会调用 notifyObservers() 方法通知所有已注册的观察者。ConcreteObserver 类是实现了 Observer 接口的具体观察者,当接收到 update() 方法调用时,会做出相应的反应。在 Main 类的测试代码中,我们创建了一个具体的被观察者对象,并添加了两个观察者,然后改变被观察者的状态,可以看到观察者都收到了通知并进行了更新。 

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

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

相关文章

python的列表生成式

什么是列表生成式&#xff1f; 列表生成式&#xff0c;顾名思义&#xff0c;是生成列表的一个简单又直接的方法。它使用了一种紧凑的语法来构造列表&#xff0c;能够以一种更清晰、更简洁的方式来表达循环和过滤逻辑。 基础示例让我们先从一些简单的例子开始&#xff1a; 「生…

echarts 基础入门

前言&#xff1a;本文档主要讲解 echarts 在 vue3 中的用法&#xff0c;及其 echarts 的一些配置参数含义及用法。示例参考 echarts 示例 一&#xff1a;快速开始 1. 安装 echarts npm install echarts # or pnpm add echarts # or yarn add echarts 2. 使用 echarts <…

通过商品id采集京东商品详情数据(含价格、优惠券、详情、主图等字段)

item_get_app-获得JD商品详情原数据 公共参数 名称类型必须描述keyString是调用key&#xff08;注册账号获取测试key&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,item_search_shop等]cach…

【八股】Spring篇

why Spring? 1.使用它的IOC功能&#xff0c;在解耦上达到了配置级别。 2.使用它对数据库访问事务相关的封装。 3.各种其他组件与Spring的融合&#xff0c;在Spring中更加方便快捷的继承其他一些组件。 IoC和DI &#x1f449;IOC是Inversion of Control的缩写&#xff0c;“…

Day4 商品管理

Day4 商品管理 这里会总结构建项目过程中遇到的问题&#xff0c;以及一些个人思考&#xff01;&#xff01; 学习方法&#xff1a; 1 github源码 文档 官网 2 内容复现 &#xff0c;实际操作 项目源码同步更新到github 欢迎大家star~ 后期会更新并上传前端项目 编写品牌服务 …

【C++】string类的增删改查模拟实现(图例超详细解析!!!)

目录 一、前言 二、string类的模拟实现 ✨前情提要 ✨Member functions —— 成员函数 ⚡构造函数 ⚡拷贝构造函数 ⚡赋值运算符重载 ⚡析构函数 ✨Element access —— 元素访问 ⚡operator[ ] ⚡Iterator —— 迭代器 ✨Capacity —— 容量 ⚡size ⚡capacity ⚡clea…

2024年 Java 面试八股文(20w字)

目录 第一章-Java基础篇 1、你是怎样理解OOP面向对象 难度系数&#xff1a;⭐ 2、重载与重写区别 难度系数&#xff1a;⭐ 3、接口与抽象类的区别 难度系数&#xff1a;⭐ 4、深拷贝与浅拷贝的理解 难度系数&#xff1a;⭐ 5、sleep和wait区别 难度系数&a…

VSCode配置Eclipse快捷键

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、下载扩展二、使用扩展总结 前言 有时候我们可能会同时使用很多种IDE&#xff0c;每种IDE又有不同的Keymap&#xff0c;快捷键用起来很头疼。比如我&#x…

免费语音转文字:自建Whisper,贝锐花生壳3步远程访问

Whisper是OpenAI开发的自动语音识别系统&#xff08;语音转文字&#xff09;。 OpenAI称其英文语音辨识能力已达到人类水准&#xff0c;且支持其它98中语言的自动语音辨识&#xff0c;Whisper神经网络模型被训练来运行语音辨识与翻译任务。 此外&#xff0c;与其他需要联网运行…

Ubuntu 20.04.6下载、安装

一、下载 下载地址&#xff1a;https://cn.ubuntu.com/download 下载版本&#xff1a;ubuntu-20.04.6-desktop-amd64.iso 二、安装 参考博客&#xff1a; https://blog.csdn.net/lhl_blog/article/details/123406322 https://www.cnblogs.com/fieldtianye/p/17879840.html…

如何使用docker部署前端项目

账号:root 密码:*** 主机:ip地址 登录后: 初级名词: sudo 是Linux和类Unix操作系统中的一个命令,全称为“super user do”,用于允许普通用户以超级用户(root)的身份执行某些或全部命令 需要下载的软件: sudo yum install 软件名 sudo yum install lrzsz 上传软件 s…

婴儿专用洗衣机有必要吗?四大宝藏婴儿洗衣机测评对比

对于有了宝宝的家庭来说&#xff0c;洗衣成为了一项重要的家务事。大家都知道&#xff0c;宝宝的皮肤比较娇嫩&#xff0c;容易受到各种细菌、病毒的侵扰。所以&#xff0c;宝宝的衣物应该与大人的分开洗。婴儿洗衣机作为一种专门为婴幼儿家庭设计的洗衣机&#xff0c;其具有除…

Spring5深入浅出篇:Spring对象属性注入详解

Spring5深入浅出篇:Spring对象属性注入详解 很多粉丝私信我这个Spring5的课程在哪看,这边是在B站免费观看欢迎大家投币支持一下. https://www.bilibili.com/video/BV1hK411Y7zf 首先需要了解什么是注入?在创建对象的过程中,不仅仅是创建一个对象还需要为对象的属性赋值.这一系…

Win11和WinRAR取消折叠菜单恢复经典菜单

这里写目录标题 前言1. Win11恢复经典右键菜单1.1 修改前1.2 恢复成经典右键菜单1.3 修改后1.4 想恢复怎么办&#xff1f; 2. WinRAR取消折叠菜单恢复经典菜单2.1 修改前2.2 修改恢复为经典菜单2.3 修改后2.4 想恢复怎么办&#xff1f; 前言 最近换回了Windows电脑&#xff0c…

SpringBoot学习(四)NoSQL、接口文档、远程调用、消息服务、Web安全、可观测性、AOT

文章目录 NoSQLRedis整合场景整合自动配置原理定制化序列化机制redis客户端 接口文档OpenAPI3架构整合使用常用注解Docket配置 远程调用WebClient创建与配置获取响应定义请求体 HTTP interface导入依赖定义接口创建代理&测试 消息服务消息队列-场景异步解耦削峰缓冲 消息队…

学习Docker笔记

在23号刚刚学完新版本的docker还想说回去继续学习老版本的springcloud课程里面的docker 结果一看黑马首页新版本课程出了&#xff0c;绷不住了。以下是我学习新版本docker的笔记&#xff0c;记录了我学习过程遇到的各种bug和解决&#xff0c;也参考了黑马老师的笔记&#xff1a…

统一SQL 支持Oracle decode函数到TDSQL-MySQL的转换

统一SQL介绍 https://www.light-pg.com/docs/LTSQL/current/index.html 源和目标 源数据库&#xff1a;Oracle 目标数据库&#xff1a;TDSQL-MySQL 操作目标 在Oracle中&#xff0c;decode函数语法如下图&#xff1a;该函数功能是将 expr与每个 search 依次做比较&#x…

告别SQL注入攻击之扰!揭秘强大防护策略,筑牢网站安全防线,畅享无忧体验!

SQL注入攻击是一种极具破坏性的Web漏洞&#xff0c;它利用应用程序对用户输入的处理不当&#xff0c;让恶意用户能够执行非授权的SQL查询&#xff0c;进而对数据库造成巨大损害。这种攻击方式可能导致数据泄露、系统崩溃等严重后果&#xff0c;因此必须引起高度重视。 为了有效…

免费又好用的五款电脑监控软件(先收藏再看)

电脑监控软件可以为企业的管理提供一臂之力&#xff0c;然而市面上的监控软件品牌众多&#xff0c;良莠不齐&#xff0c;导致企业不知道用哪个&#xff0c;今天为大家盘点免费又好用的五款电脑监控软件。 安企神&#xff08;点击试用7天&#xff09; 安企神是一款专业的电脑监…

OpenAIGPT-4.5提前曝光?

OpenAI GPT-4.5的神秘面纱&#xff1a;科技界的震撼新篇章 在人工智能的世界里&#xff0c;每一次技术的飞跃都不仅仅是一次更新&#xff0c;而是对未来无限可能的探索。近日&#xff0c;科技巨头OpenAI似乎再次站在了这场革命的前沿&#xff0c;其潜在的新产品——GPT-4.5 Tur…
最新文章