设计模式行为型——观察者模式

目录

什么是观察者模式

观察者模式的实现

观察者模式角色

观察者模式类图

观察者模式举例

观察者模式代码实现

观察者模式的特点

优点

缺点

使用场景

注意事项

实际应用


什么是观察者模式

        观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会自动收到通知并更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

观察者模式的实现

观察者模式角色

  1. 主题角色(Subject):也称为被观察者或可观察者,它是具有状态的对象,并维护着一个观察者列表。主题提供了添加、删除和通知观察者的方法。这个角色可以是接口,也可以是抽象类或者具体的类,因为很多情况下会与其他的模式混用,所以使用抽象类的情况比较多。
  2. 具体主题角色(Concrete Subject):具体主题是主题的具体实现类。它维护着观察者列表,并在状态发生改变时通知观察者。同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。
  3. 观察者角色(Observer):观察者是接收主题通知的对象。观察者需要实现一个更新方法,当收到主题的通知时,调用该方法进行更新操作。
  4. 具体观察者角色(Concrete Observer):具体观察者是观察者的具体实现类。它实现了更新方法,定义了在收到主题通知时需要执行的具体操作。存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致。

观察者模式类图

观察者模式举例

观察者模式代码实现

主题角色

package com.common.demo.pattern.observer;

import java.util.Vector;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 主题角色
 * @date 2023/08/07 10:37:05
 */
public abstract class Subject {
    private Vector<Observer> obs = new Vector();

    public void addObserver(Observer obs) {
        this.obs.add(obs);
    }

    public void delObserver(Observer obs) {
        this.obs.remove(obs);
    }

    protected void notifyObserver() {
        for (Observer o : obs) {
            o.update();
        }
    }

    public abstract void doSomething();
}

具体主题角色

package com.common.demo.pattern.observer;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 具体主题角色
 * @date 2023/08/07 10:39:23
 */
public class ConcreteSubject extends Subject{

    @Override
    public void doSomething(){
        System.out.println("被观察者事件发生改变");
        this.notifyObserver();
    }
}

观察者角色

package com.common.demo.pattern.observer;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 观察者角色 观察者接口
 * @date 2023/08/07 10:30:26
 */
public interface Observer {
    void update();
}

具体观察者角色

package com.common.demo.pattern.observer;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 具体观察者角色 观察者角色A
 * @date 2023/08/07 10:40:54
 */
public class ConcreteObserverA implements Observer{

    @Override
    public void update() {
        System.out.println("观察者A收到信息,并进行业务处理");
    }
}
package com.common.demo.pattern.observer;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 具体观察者角色 观察者角色B
 * @date 2023/08/07 10:40:54
 */
public class ConcreteObserverB implements Observer{

    @Override
    public void update() {
        System.out.println("观察者B收到信息,并进行业务处理");
    }
}

测试类

package com.common.demo.pattern.observer;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 测试类
 * @date 2023/08/07 10:46:55
 */
public class ClientTest {

    public static void main(String[] args) {
        Subject sub = new ConcreteSubject();
        sub.addObserver(new ConcreteObserverA());
        sub.addObserver(new ConcreteObserverB());
        sub.doSomething();

    }
}

测试截图

观察者模式的特点

优点

  1. 实现了松耦合:观察者模式可以将被观察者和观察者之间的耦合度降低,使得它们可以独立地进行扩展和修改。
  2. 支持广播通信:建立一套广播通信触发机制,被观察者可以同时通知多个观察者,从而支持广播通信的需求。
  3. 符合开闭原则:新增或删除观察者不会影响到被观察者和其他观察者的代码,符合开闭原则的要求。

缺点

  1. 观察者过多可能导致性能问题:如果观察者过多或者观察者的处理逻辑复杂,会影响到系统的性能,花费较多的时间。
  2. 观察者和被观察者直接关联:在一些情况下,观察者和被观察者之间的直接关联可能会导致设计上的困扰。
  3. 观察者和观察目标循环依赖:在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 
  4. 观察者对所观察的目标对象黑盒操作:无相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景

  1. 当一个对象的改变需要通知其他对象,并且不希望将对象之间的耦合度过高时,可以考虑使用观察者模式。
  2. 当某个对象的状态改变需要引起一系列相关对象的更新时,不需要知道这些对象是谁,不需知道具体有多少对象有待改变,可以使用观察者模式。
  3. 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。

注意事项

  1. 注意观察者和被观察者的关联方式:可以通过接口或抽象类定义观察者接口,使得被观察者只与接口进行交互,而不依赖于具体的观察者实现类。
  2. 避免循环依赖:观察者和被观察者之间应该避免出现循环依赖的情况,否则可能导致无限循环的通知。
  3. 如果顺序执行,某一观察者错误会导致系统卡壳,可采用异步方式进行通知。

实际应用

  1. 网络订阅服务:订阅者可以订阅感兴趣的内容,当内容更新时,订阅者会收到通知。
  2. 消息中间件:多个消息消费者可以同时监听一个消息主题,当主题发布消息时,所有消费者都会接收到通知并处理消息。
  3. GUI界面组件:GUI界面中的事件监听机制就是一种观察者模式的实现。

更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)

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

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

相关文章

安全作业-Race竞争型漏洞、原型链污染

1.race漏洞一直卡在虚拟机安装上(待研究) 2.原型链污染 一、第一题js代码 const express require(express) var hbs require(hbs); var bodyParser require(body-parser); const md5 require(md5); var morganBody require(morgan-body); const app express(); var use…

谈谈对Android音视频开发的探究

在日常生活中&#xff0c;视频类应用占据了我们越来越多的时间&#xff0c;各大公司也纷纷杀入这个战场&#xff0c;不管是抖音、快手等短视频类型&#xff0c;虎牙、斗鱼等直播类型&#xff0c;腾讯视频、爱奇艺、优酷等长视频类型&#xff0c;还是Vue、美拍等视频编辑美颜类型…

《Zookeeper》从零开始学Zookeeper源码(二)之数据序列化与通信协议

目录 序列化与反序列化通信协议请求头的数据结构响应头的数据结构 序列化与反序列化 zookeeper的客户端与服务端、服务端与服务端之间会进行一系列的网络通信&#xff0c;在进行数据的传输过程中就涉及到序列化与反序列化&#xff0c;zookeeper使用Jute作为它的序列化组件&…

红队钓鱼技术之自解压钓鱼木马

简介 对于使用自解压文件的场景&#xff0c;攻击者可以创建一个自解压的exe文件&#xff0c;该文件解压后自动执行解压出来的文件。然后&#xff0c;通过插入RLO字符&#xff0c;将这个exe文件伪装成另一种看似安全的文件类型&#xff0c;比如文本文件或图片文件。当用户打开这…

decimal类型在MySQL中的正确使用 (长度和小数点)

1. MySQL(decimal) 对应 Java(BigDecimal) 2. decimal(16,2) MySQL中类型的设置, 长度16, 保留2位小数 3. 如果长度小于14, 则会出现没小数位的情况

Mybatis异常Invalid bound statement (not found)原因之Mapper文件配置不匹配

模拟登录操作 $.post("/admin/login", {aname, pwd }, rt > {if (rt.code 200) {location.href "manager/index.html";return;}alert(rt.msg)});网页提示服务器代码错误 POST http://localhost:8888/admin/login 500后端显示无法找到Mapper中对应的…

基于EIoT能源物联网的工厂智能照明系统应用改造-安科瑞黄安南

【摘要】&#xff1a;随着物联网技术的发展&#xff0c;许多场所针对照明合理应用物联网照明系统&#xff0c;照明作为工厂的重要能耗之一&#xff0c;工厂的照明智能化控制&#xff0c;如何优化控制、提高能源的利用率&#xff0c;达到节约能源的目的。将互联网的技术应用到工…

手机便签内容不见了怎么恢复正常?

在日常生活和工作中&#xff0c;很多人都需要随手记录事情&#xff0c;例如家庭琐事、孩子相关的事情、指定时间需要完成的工作任务、会议安排等。当我们需要随时随地记录事情的时候&#xff0c;手机便签应用就是非常不多的选择&#xff0c;我们直接打开手机上的便签APP就可以新…

爬虫009_字符串高级_替换_去空格_分割_取长度_统计字符_间隔插入---python工作笔记028

然后再来看字符串的高级操作 取长度 查找字符串下标位置 判断是否以某个字符,开头结尾 计算字符出现次数 替换

一、Webpack相关(包括webpack-dev-server用以热更新和html-webpack-plugin)

概念与功能&#xff1a; webpack是前端项目工程化的具体解决方案。它提供了友好的前端模块化开发支持&#xff0c;以及代码压缩混淆、处理浏览器端JavaScript的兼容性、性能优化等强大的功能。 快速上手&#xff1a;隔行变色 -S实际是--save的简写&#xff0c;表示安装的第三方…

0基础学习VR全景平台篇 第79篇:全景相机-泰科易如何直播推流

泰科易科技是中国的一家研发全景相机的高科技公司&#xff0c;前不久&#xff0c;在2020世界VR产业大会上发布了新一代5G VR直播影像采集终端--360starlight。以其出色的夜景成像效果和一“部”到位的直播方案重新定义了VR慢直播相机&#xff0c;对行业具有高度借鉴意义。 本文…

嵌入式开发学习(STC51-18-LCD液晶显示)

内容 在LCD1602液晶上显示字符信息&#xff1b; LCD1602介绍 简介 1602液晶也叫1602字符型液晶&#xff0c;它能显示2行字符信息&#xff0c;每行又能显示16个字符&#xff1b; 它是一种专门用来显示字母、数字、符号的点阵型液晶模块&#xff1b; 它是由若干个5x7或者5x…

嵌入式学习之震动喇叭项目

震动喇叭项目所用到的元器件有振动传感器模块、继电器模块、高功率喇叭、433M无线发射接收模块&#xff0c;通过这些模块&#xff0c;能够实现做出一个智能报警系统的项目出来&#xff0c;非常的有趣&#xff0c;特别是喇叭声音想起来&#xff0c;那个声音挺大的。 继电器的学…

【Java从0到1学习】06 Java 面向对象

1. 面向对象思想 面向对象是一种符合人类思维习惯的编程思想。现实生活中存在各种形态不同的事物&#xff0c;这些事物之间存在着各种各样的联系。在程序中使用对象来映射现实中的事物&#xff0c;使用对象的关系来描述事物之间的联系&#xff0c;这种思想就是面向对象。 提到…

RocketMQ 主备自动切换模式部署

目录 主备自动切换模式部署 Controller 部署​ Controller 嵌入 NameServer 部署​ Controller 独立部署​ Broker 部署​ 兼容性​ 升级注意事项​ 主备自动切换模式部署 该文档主要介绍如何部署支持自动主从切换的 RocketMQ 集群&#xff0c;其架构如上图所示&#xff…

Spring Boot数据访问基础知识与JDBC简单实现

目录 Spring Boot数据访问基础知识 Spring Data ORM JDBC JPA JDBC简单实现 步骤1&#xff1a;新建Maven项目&#xff0c;添加依赖 步骤2&#xff1a;配置数据源—让程序可以访问到 步骤3&#xff1a;配置数据源—让IDEA可以访问到 步骤4&#xff1a;添加数据库和表 …

【网络编程·传输层】UDP和TCP的报头

目录 一、端口号划分 二、部分指令 1、pidof&#xff08;用于查看进程id&#xff09; 2、netstat&#xff08;查看网络状态&#xff09; 三、UDP协议 1、UDP协议格式 2、UDP协议如何进行封装、解包、分用 2.1封装、解包 2.2分用 3、UDP协议的特点 3.1UDP协议的特点 …

CMake 3.13.4 or higher is required. You are running version 3.10.2

ubuntu 安装 cmake&#xff0c;但是apt安装的版本太低&#xff0c;需要其他安装方法。 参考视频 https://www.youtube.com/watch?v_yFPO1ofyF0 以下是对视频内容的提炼&#xff0c;就两点 1、下载需要版本的sh文件&#xff1b;2、安装 一、下载需要版本的sh文件 https://cma…

什么是GCC

GCC&#xff08;GNU Compiler Collection&#xff0c;GNU编译器套件&#xff09;是由 GNU 开发的编程语言译器。GNU 编译器套件包括 C、C、Objective-C、Java、Ada 和 Go 语言前端&#xff0c;也包括了这些语言的库&#xff08;如 libstdc&#xff0c;libgcj等&#xff09; GC…

【gavh39芯片用什么代替-AH8652】

问&#xff1a;gavh39芯片用什么代替&#xff1f; 答&#xff1a;gavh39是一颗用于交流220v转5v输出的芯片&#xff0c;它的拼对拼代替型号为AH8652 AH8652是一款非隔离电源管理芯片&#xff0c;它用于将交流电压转换为直流电压输出。可以将输入的220V交流电转换为输出的5V直流…