【设计模式深度剖析】【7】【行为型】【观察者模式】

news2024/11/16 21:53:42

👈️上一篇:中介者模式

设计模式-专栏👈️

---

文章目录

  • 观察者模式
    • 英文原文
    • 直译
    • 如何理解?
  • 观察者模式的角色
    • 类图
    • 代码示例
  • 观察者模式的应用
    • 观察者模式的优点
    • 观察者模式的缺点
    • 观察者模式的使用场景

观察者模式

观察者模式Observer Pattern

观察者(Observer)也称发布-订阅(Publish-Subscribe),依赖(Dependents)。

观察者模式就像是一群订阅了报纸的读者,每当报纸有新版发布(状态更新),就会自动送到这些读者的手中,读者们可以根据自己的兴趣选择阅读哪些内容。这样,读者和报纸之间形成了一种灵活、低耦合的订阅-发布关系。

英文原文

The Observer Design Pattern is a behavioral design patternthat defines a one-to-many dependency between objects so that when one object (the subject) changes state, all its dependents (observers) are notified and updated automatically.

直译

观察者设计模式(Observer Design Pattern)是一种行为设计模式,它定义了对象之间的一对多依赖关系,以便当一个对象(主题)改变其状态时,其所有依赖者(观察者)都能得到通知并自动更新。

如何理解?

观察者模式就像是一群朋友在关注一个公告板。公告板是被观察者,而朋友们是观察者。当公告板上的内容发生变化(比如有新的活动通知)时,所有关注这个公告板的朋友们(观察者)都会收到通知,并根据通知的内容做出相应的反应(比如参加活动)。这样,即使公告板的内容经常变化,朋友们也不需要一直盯着它看,只要他们关注了公告板,就能在第一时间得到通知。这种模式不仅方便了朋友们获取信息,也减轻了公告板的负担。

观察者模式的角色

观察者模式通常包含以下几个角色:

  1. Subject(主题/被观察者):它知道有哪些观察者对其感兴趣,并提供了一个接口让观察者能注册自己、移除自己以及通知它们。
  2. Observer(观察者):为那些在主题状态改变时需要获得通知的对象定义一个更新接口。
  3. ConcreteSubject(具体主题):保存有关状态的信息,并提供一个接口供观察者查询状态、注册和移除自己。
  4. ConcreteObserver(具体观察者):实现观察者接口,以便在主题的状态发生改变时得到更新。

类图

在这里插入图片描述

代码示例

package com.polaris.designpattern.list3.behavioral.pattern07.observer.classicdemo;

import java.util.ArrayList;
import java.util.List;

interface Observer {
    void update(String message);
}


interface Subject {
    void registerObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObservers(String message);
}

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 setState(String state) {
        // 状态改变时,通知所有观察者  
        notifyObservers("Subject state has changed to: " + state);
    }
}

class ConcreteObserver implements Observer {
    private String name;

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

    @Override
    public void update(String message) {
        System.out.println(name + " has been notified: " + message);
    }
}


public class ObserverPatternDemo {
    public static void main(String[] args) {
        Subject subject = new ConcreteSubject();

        System.out.println("registerObserver: Observer 1, Observer 2...");
        Observer observer1 = new ConcreteObserver("Observer 1");
        Observer observer2 = new ConcreteObserver("Observer 2");

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

        System.out.println("change subject state...");
        // 改变主题状态,这将触发所有注册的观察者的update方法  
        ((ConcreteSubject) subject).setState("New state");

        // 移除一个观察者
        System.out.println("remove observer1...");
        subject.removeObserver(observer1);

        System.out.println("change subject state...");
        // 再次改变主题状态,只会通知未移除的观察者  
        ((ConcreteSubject) subject).setState("Another new state");
    }
}

/* Output:
registerObserver: Observer 1, Observer 2...
change subject state...
Observer 1 has been notified: Subject state has changed to: New state
Observer 2 has been notified: Subject state has changed to: New state
remove observer1...
change subject state...
Observer 2 has been notified: Subject state has changed to: Another new state
*///~

上面示例当主题的状态改变时,所有注册的观察者都会收到通知并更新它们的状态。当某个观察者被移除后,它将不再收到通知。

观察者模式的应用

  1. 图形用户界面(GUI)开发:在GUI中,当用户与界面上的元素(如按钮、文本框)进行交互时,这些元素的状态可能会发生变化。观察者模式可以用于将这些状态变化通知给相应的观察者,触发相应的操作或更新界面。
  2. 消息通知系统:在聊天应用、社交媒体平台等需要实时消息传递的场景中,观察者模式可以实现消息的订阅与发布。当有新消息发布时,订阅该消息的观察者将收到通知并进行处理。
  3. 股票市场:股票交易所可以充当被观察者,而股票交易员可以充当观察者。当股票的价格、交易量等发生变化时,交易员将接收到通知并采取相应的行动。
  4. 日志记录系统:日志记录器可以充当被观察者,而观察者可以是日志分析器、报警系统等。当日志发生变化时,观察者将收到通知并执行相应的操作,如生成报告、发送警报等。

观察者模式的优点

  1. 解耦:观察者和被观察者是抽象耦合的,降低了它们之间的依赖关系,使得系统更加灵活和可扩展。
  2. 广播通信:支持一对多的依赖关系,简化了系统设计。
  3. 满足开闭原则:增加新的具体观察者或观察目标时,无需修改原有系统代码。

观察者模式的缺点

  1. 性能问题:如果一个被观察者对象有很多的直接和间接的观察者,将所有的观察者都通知到会花费很多时间,可能导致性能下降。
  2. 循环依赖问题:如果观察者和观察目标之间存在循环依赖,可能导致系统崩溃。
  3. 缺乏细节:观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

观察者模式的使用场景

  1. 当一个对象的改变需要同时改变其他对象时:可以使用观察者模式,将需要改变的对象作为观察者,将发生变化的对象作为被观察者。
  2. 当一个对象必须通知其他对象,但又不希望这些对象与它形成紧密耦合时:通过观察者模式,可以实现对象之间的松耦合关系。

---

👈️上一篇:中介者模式

设计模式-专栏👈️

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

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

相关文章

【React】配置别名路径@

别名路径配置 1. 路径解析配置&#xff08;webpack&#xff09; CRA本身把webpack配置包装到了黑盒里无法直接修改&#xff0c;需要借助一个插件 - craco步骤 安装craco npm i -D craco/craco项目根目录下创建配置文件 craco.config.js配置文件中添加路径解析配置 const pa…

Android低代码开发 - 直接创建一个下拉刷新列表界面

看了我Android低代码开发 - 让IDE帮你写代码这篇文章的小伙伴&#xff0c;大概都对Dora全家桶开发框架有基本的认识了吧。本篇文章将会讲解如何使用dora-studio-plugin快捷创建一个下拉刷新列表界面。 效果演示 这样直接通过图形界面的方式就创建好了下拉刷新上拉加载空态界面…

3. 打造个性化可爱怪物表情包:详细步骤教学

表情符号已经成为当今互联网对话中不可或缺的元素&#xff0c;一句话加上一个笑脸符号&#xff0c;语气就大不同。表情符号与我们一道稳步发展&#xff0c;成为鲜活和丰富情感的必要交流工具。通过表情符号&#xff0c;几个像素就能以有趣、清晰、能引起情感共鸣的方式表达我们…

d3dcompiler_43.dll是什么文件?怎么高效率的解决d3dcompiler_43.dll丢失问题

d3dcompiler_43.dll是什么文件&#xff1f;当你知道d3dcompiler_43.dll这个文件名字的时候&#xff0c;相信你是遇到了d3dcompiler_43.dll丢失的问题了&#xff01;所以才会这样问&#xff0c;其实这就是一个普通的dll文件&#xff0c;对于电脑系统有着至关重要的作用&#xff…

100v 高耐压ldo 高压三端稳压芯片

100v 高耐压ldo 高压三端稳压芯片

【Android 11】AOSP Settings添加屏幕旋转按钮

前言 这里是客户要求添加按钮以实现屏幕旋转。屏幕旋转使用adb的命令很容易实现&#xff1a; #屏幕翻转 adb shell settings put system user_rotation 1 #屏幕正常模式 adb shell settings put system user_rotation 0这里的值可以是0&#xff0c;1&#xff0c;2&#xff0c…

pyinstaller打包exe多种失败原因解决方法

pyinstaller打包exe多种失败原因解决方法 目录 pyinstaller打包exe多种失败原因解决方法1、pyinstaller安装有问题1.1 安装pyinstaller1.2 采用anconda的环境启动 2、pyqt5与pyside6冲突2.1 打包生成.spec文件2.2 编辑spec文件 3、打包成功后打不开exe&#xff0c;exe闪退3.1 s…

网格重构技术在AI绘画中的革新作用

引言&#xff1a; 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;艺术创作也迎来了前所未有的变革。AI绘画不仅改变了艺术家的创作方式&#xff0c;还为非专业人士开启了艺术创作的大门。在众多AI技术中&#xff0c;网格重构技术因其独特的作用和效果成为A…

【CH32V305FBP6】USBD HS 中断分析

文章目录 前言中断分析 USBHS_IRQHandler传输完成&#xff1a;USBHS_UIF_TRANSFERTOKEN_IN&#xff1a;发送完成TOKEN_OUT&#xff1a;接收完成 描述符&#xff1a;USBHS_UIF_SETUP_ACT总线复位&#xff1a;USBHS_UIF_BUS_RST总线挂起&#xff1a;USBHS_UIF_SUSPEND 前言 所有…

图文解析ASN.1中BER编码:结构类型、编码方法、编码实例

本文将详细介绍ASN.1中的BER编码规则&#xff0c;包括其编码机制、数据类型表示、以及如何将复杂的数据结构转换为二进制数据。通过本文的阅读&#xff0c;读者将对ASN.1中的BER编码有一个全面的理解。 目录 一.引言 二.BER编码基本结构 ▐ 1. 类型域&#xff08;Type&#…

光伏气象站:智能驱动,助力光伏产业绿色发展

TH-FGF9在全球能源结构转型和环境保护的大背景下&#xff0c;分布式光伏发电以其清洁、可再生的特性&#xff0c;逐渐成为了能源领域的新宠。然而&#xff0c;光伏发电的效率受气象条件影响较大&#xff0c;如光照强度、温度、风速等因素都会对光伏电站的发电效率产生直接影响。…

flask实战之模板实现公共导航

基础实现 目标 在Flask中&#xff0c;使用模板继承和块&#xff08;blocks&#xff09;可以方便地提取公共导航菜单&#xff0c;使得您可以在多个页面上重用相同的导航结构。以下是一个基本示例&#xff0c;展示如何创建一个包含公共导航菜单的模板&#xff1a; 创建基础模板…

Python-Socket网络编程简单示例

# TCP 服务端程序 server.py # 导入socket 库 from socket import *# 主机地址为空字符串&#xff0c;表示绑定本机所有网络接口ip地址 # 等待客户端来连接 IP # 端口号 PORT 50000 # 定义一次从socket缓冲区最多读入512个字节数据 BUFLEN 512# 实例化一个socket对象 # 参…

实测完快手的AI视频「可灵」后,我觉得这才是第一个中国版Sora

6月6号&#xff0c;是快手的13周年生日。 在这一天&#xff0c;所有AI圈的人都想不到&#xff0c;快手在13周年之际&#xff0c;没有任何预兆、没有任何宣传&#xff0c;直接发布了他们的AI视频大模型。 可灵。 给我也干了个措手不及。 我当时正在看360的发布会&#xff0c;…

SD5510 单节锂离子电池充电器和恒定5V升压控制器芯片IC

一般描述 SD5510为一款移动电源专用的单节锂离子电池充电器和恒定5V升压控制器&#xff0c;充电部分集高 精度电压和充电电流调节器、预充、充电状态指示和充电截止等功能于一体&#xff0c;可以输出最大1A充电电流。而升压电路采用CMOS工艺制造的空载电流极低的VFM开关…

SpringBoot不用写Controller、不用写Service、不用建表,直接起飞是什么感觉

Spring Data REST 提供了一种简单的方式来暴露 JPA 实体为 RESTful 服务&#xff0c;这使得构建基于 REST 的数据服务变得非常快速和高效。下面是一个使用 Spring Data REST 构建通用架构的基本示例&#xff1a; 首先&#xff0c;我们需要创建一个实体类&#xff08;例如&…

Centos离线安装Python3

目录 1.准备工作 2.解压python压缩包 3.编译 4.安装、更改环境变量 5.建立pip连接 使用的是Centos7服务器&#xff0c;Py版本是py3.9.0 1.准备工作 首先确保服务器中存在相关的编译器&#xff0c;例如GCC&#xff1b;这里不做过多叙述&#xff0c;需要者前往&#xff1a…

【全开源】旅行吧旅游门票预订系统源码(FastAdmin+ThinkPHP+Uniapp)

&#x1f30d;旅游门票预订系统&#xff1a;畅游世界&#xff0c;一键预订 一款基于FastAdminThinkPHPUniapp开发的旅游门票预订系统&#xff0c;支持景点门票、导游产品便捷预订、美食打卡、景点分享、旅游笔记分享等综合系统&#xff0c;提供前后台无加密源码&#xff0c;支…

milvus的GPU索引

前言 milvus支持多种GPU索引类型&#xff0c;它能加速查询的性能和效率&#xff0c;特别是在高吞吐量&#xff0c;低延迟和高召回率的场景。本文我们将介绍milvus支持的各种GPU索引类型以及它们适用的场景、性能特点。 下图展示了milvus的几种索引的查询性能对比&#xff0c;…

40. 【Java教程】数据库编程

本小节我们将学习如何使用 Java 语言结合数据库进行编程。注意&#xff0c;学习本小节需要你有一定的 SQL 基础&#xff0c;了解 MySQL 数据库的 基础 CRUD 操作。 本小节我们将选择开源免费的 MySQL 5.7 作为数据库&#xff0c;可以去官网下载并安装 MySQL。 通过本小节的学…