Java设计模式-观察者模式/观察者模式适合那些场景?怎么使用

news2024/9/28 21:27:07

继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用!

6.7 观察者模式

6.7.1 定义

  • 又称发布-订阅模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象
  • 主体对象在状态变化时,会通知所有的观察者对象,使其自动更新

6.7.2 结构

  • 抽象主题(被观察者):将所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,提供一个接口来增加和删除观察者对象
  • 具体主题(具体被观察者):将有关状态存入具体观察者对象,在具体主题内部状态发生改变时,给所有注册过得观察者发送通知
  • 抽象观察者:观察者的抽象类,定义了一个更新接口,使得在得到主题更改时通知更新自己
  • 具体观察者:实现抽象观察者定义的更新接口,以便得到主题更改时更新自身状态

6.7.3 案例(微信公众号)

  • 抽象观察者
public interface Observer {  
//    自动更新方法  
    void update(String model);  
}
  • 抽象主题
public interface Subject {  
    //    删除观察者  
    void deleteSubject(Observer observer);  
    //    添加观察者  
    void addSubject(Observer observer);  
//    通知观察者对象  
    void notify(String message);  
}
  • 具体主题
public class Subscription implements Subject{  
//    集合,用来存储观测察者对象  
    List<Observer> observerList = new ArrayList<Observer>();  
    @Override  
    public void deleteSubject(Observer observer) {  
        observerList.remove(observer);  
    }  
    @Override  
    public void addSubject(Observer observer) {  
        observerList.add(observer);  
    }  
    @Override  
    public void notify(String message) {  
//        遍历通知集合中的对象  
        for (Observer observer : observerList) {  
            observer.update(message);  
        }  
    }  
}
  • 具体观察者
public class WeChatObserver implements Observer{  
    String name;  
    public WeChatObserver(String name) {  
        this.name = name;  
    }  
    @Override  
    public void update(String message) {  
        System.out.println(name +"-" + message);  
    }  
}
  • 测试
    public static void main(String[] args) {  
//        创建公众号对象  
        Subscription subscription = new Subscription();  
//        创建订阅者  
        WeChatObserver weChatObserver = new WeChatObserver("张三");  
        WeChatObserver weChatObserver1 = new WeChatObserver("李四");  
        WeChatObserver weChatObserver2 = new WeChatObserver("王五");  
        subscription.addSubject(weChatObserver);  
        subscription.addSubject(weChatObserver1);  
        subscription.addSubject(weChatObserver2);  
        subscription.notify("更新");  
    }
  • 结果
    ![[Pasted image 20230115200248.png]]- 类图![[Pasted image 20230115200318.png]]

6.7.4 优缺点

6.7.4.1 优点

  • 降低了目标与观察者之间耦合关系,是抽象耦合
  • 被观察者发送通知,所有注册的观察者都收到信息(广播机制)

6.7.4.2 缺点

  • 若观察者多,则所有观察者收到被观察者发送的通知会耗时
  • 若观察者有循环依赖,则所有观察者发送通知会使观察者循环调用,导致系统崩溃

6.7.5 使用场景

  • 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象
  • 当抽象模型有两方面,其中一个方面依赖另一个方面

6.7.6 JDK源码

Java中,通过java.util.Observerable类和java.util.Observer定义观察者模式,实现子类就可编写观察者实例

6.7.6.1 Observable

  • 抽象目标类(被观察者),有vector集合成员变量,用于保存所有要通知的观察者对象,重要方法如下:
  • void addObserver(Observer o):将新观察者对象添加到集合中
  • void notifyObservers(Object o):调用集合中所有观察者对象的update方法,越晚加入的观察者越先被通知
  • void setChange():设置内部状态boolean类型标志,表明目标对象发生变化了,true时notifyObservers()方法执行

6.7.6.2 Observer接口

  • 抽象观察者,监视目标对象,档期发生变化时观察中得到通知,并调用update()方法

6.7.6.3 案例(警察抓小偷)

  • 具体主题
public class Thief extends Observable {  
    String name;  
    public Thief(String name) {  
        this.name = name;  
    }  
    public void steal(){  
        System.out.println("小偷" + name + ":不好,偷东西被发现啦");  
        super.setChanged();  
        super.notifyObservers();  
    }  
    public String getName() {  
        return name;  
    }  
}
  • 具体观察者
public class Policeman implements Observer {  
    @Override  
    public void update(Observable o, Object arg) {  
        System.out.println("警察:" +((Thief) o).getName() + "你已经被包围了,投降不投降?");  
    }  
}
  • 测试
public static void main(String[] args) {  
    Thief thief = new Thief("王五");  
    Policeman policeman1 = new Policeman();  
    Policeman policeman2 = new Policeman();  
    thief.addObserver(policeman1);  
    thief.addObserver(policeman2);  
    thief.steal();  
}
  • 结果![[Pasted image 20230115203733.png]]

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

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

相关文章

[前端笔记——CSS] 9.CSS处理文件的标准流程+DOM

[前端笔记——CSS] 9.CSS处理文件的标准流程DOM1.CSS处理文件的标准流程2.关于DOM2.1 举个例子2.2 应用 CSS 到 DOM1.CSS处理文件的标准流程 当浏览器展示一个文件的时候&#xff0c;它必须兼顾文件的内容和文件的样式信息&#xff0c;CSS处理文件的标准流程如下&#xff1a; …

06_FreeRTOS临界区代码保护

目录 临界段代码保护简介 临界段代码保护函数介绍 任务级临界区函数详解 中断级临界区函数详解 临界段代码保护简介 什么是临界段:临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段 适用场合如: 1.外设:需严格按照时序初始化的外设:IIC、SPI等等 2.系统…

国家发明专利:基于改进型黏菌优化算法的业务资源分配方法

国家发明专利&#xff1a;基于改进型黏菌优化算法的业务资源分配方法 摘要 本发明公开了一种基于改进型黏菌优化算法的业务资源分配方法&#xff0c;其步骤包括&#xff1a;1将生产任务分成若干个环节&#xff0c;构建有向环状分配网络&#xff1b;2构建工厂参数矩阵并归一化&…

力扣98.验证二叉搜索树

文章目录力扣98.验证二叉搜索树题目描述算法思路代码实现力扣98.验证二叉搜索树 题目描述 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。 节点的右子树只包含 …

领域驱动设计(DDD)的几种典型架构介绍

我们生活中都听说了DDD&#xff0c;也了解了DDD&#xff0c;那么怎么将一个新项目从头开始按照DDD的过程进行划分与架构设计呢&#xff1f; 一、专业术语 各种服务 IAAS&#xff1a;基础设施服务&#xff0c;Infrastructure-as-a-service PAAS&#xff1a;平台服务&#xff0c…

【Java寒假打卡】JavaWeb-Servlet基础

【Java寒假打卡】JavaWeb-Servlet基础介绍servlet快速入门servlet的执行过程servlet关系视图Servlet实现方式-继承HTTPSERVLETServlet的生命周期线程安全问题servlet的映射方式案例-多路径映射问题-指定名称的方式Servlet的创建时机默认Servlet介绍 servlet是运行在Java服务器…

免费分享一套 SpringBoot + Vue + ElementUI 的人力资源管理系统,挺漂亮的

大家好&#xff0c;我是锋哥&#xff0c;看到一个不错的SpringBoot Vue ElementUI 的人力资源管理系统&#xff0c;分享下哈。 项目介绍 项目背景 人力资源管理是企业运营中必不可少的一环&#xff0c;它关系到企业的前途与发展。尤其对于中小微企业来说&#xff0c;对企业…

积分分离PID控制算法及仿真-1

在普通 PID 控制中引入积分环节的目的&#xff0c;主要是为了消除静差&#xff0c;提高控制精度。但在过程的启动、结束或大幅度增减设定时&#xff0c;短时间内系统输出有很大的偏差&#xff0c;会造成PID运算的积分积累&#xff0c;致使控制量超过执行机构可能允许的最大动作…

Vue项目基础环境搭建完整步骤

使用vue官方脚手架(vue-cli) vue-cli简介 Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统&#xff0c;是一个官方脚手架&#xff0c;可以帮助我们快速创建vue项目工程目录&#xff0c;目前最新版本4.x。 Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保了各种构建…

第三天总结 之 商品管理界面的实现 之 模糊查询 与 数据在页面展示

商品管理界面的实现 模糊查询 第一步&#xff1a; 明确 查询时 需要的 条件 即sql语句中 where 后的条件 如 &#xff1a; 根据前端 可以发现 模糊查询可以通过 商品名称 日期 商品类型 来查询 所以在对应的controller层下的GoodsFuzzySelectServlet中首先要获取这三个属性的…

《深入浅出计算机组成原理》学习笔记 Day6

二进制编码1. “逢二进一”2. 字符串的表示参考1. “逢二进一” 把一个二进制数对应到十进制&#xff0c;就是把从右到左的第 N 位&#xff0c;乘上一个2 的 N 次方&#xff0c;然后加起来&#xff0c;就成了一个十进制数。从右到左的位置&#xff0c;是从 0 开始的。 例如&a…

初识C语言:IDE的选择与使用【C语言】

本文是本专栏【C语言】的第一篇文章&#xff0c;也是博主最近半年以来的更新第一篇文章&#xff0c;如果觉得有帮助&#xff0c;可以点赞支持一下&#xff01;另外本专栏最后会做一篇类似于【python爬虫】专栏最后的那篇整合的文章&#xff0c;把C语言的所有基础知识用一篇文章…

深度学习 GNN图神经网络(三)模型思想及文献分类案例实战

如果你有一定神经网络的知识基础&#xff0c;想学习GNN图神经网络&#xff0c;可以按顺序参考系列文章&#xff1a; 深度学习 GNN图神经网络&#xff08;一&#xff09;图的基本知识 深度学习 GNN图神经网络&#xff08;二&#xff09;PyTorch Geometric&#xff08;PyG&#x…

Nginx入门与应用

NginxNginx概述Nginx介绍Nginx下载和安装windowsLinuxNginx目录结构Nginx命令查看版本检查配置文件正确性启动和停止重新加载配置文件Nginx环境变量&#xff08;Linux&#xff09;Nginx配置文件结构Nginx具体应用部署静态资源反向代理负载均衡Nginx概述 Nginx介绍 Nginx是一款…

Linux系统——基础IO

要努力&#xff0c;但不要着急&#xff0c;繁花锦簇&#xff0c;硕果累累&#xff0c;都需要过程&#xff01; 目录 1.文件基础必备概念 2.文件系统调用接口 1.open && close 2.write 3.read 3.文件描述符fd 3.1什么是文件描述符 3.2文件描述符意义 3.3文件描述符的分配…

【C++】map和set的模拟实现

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《吃透西嘎嘎》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;红黑树的…

一个线程如何处理多个连接?(非阻塞IO)

从BIO到NIO的转变 五种IO模型BIO的缺陷非阻塞非阻塞IO&#xff08;NIO&#xff09;非阻塞读非阻塞写非阻塞IO模型php NIO 实现适用场景什么是C10k问题&#xff1f;C10K问题的由来五种IO模型 在《UNIX 网络编程》一书中介绍了五种IO模型&#xff1a; 分别是 BIO&#xff0c;NIO…

无线电基础电路 > RLC阻尼系数计算仿真

随机搭建电路如下图所示&#xff1a; 阻尼系数的希腊字母符号“ ζ ”读作泽塔。 阻尼系数ζ (R/2) * √C/L 1000/2 * √0.00001 1.58 包括三种情况&#xff1a; ζ>1&#xff1a;过阻尼&#xff0c;频响不利落&#xff0c;需要较长时间才能消失。 ζ<1&#xff…

MinIO基本使用(实现上传、下载功能)

MinIO基本使用&#xff08;实现上传、下载功能&#xff09;1.简介2.下载和安装3.启动服务端4.创建User和Bucket4.1 创建User4.1.1 生成accessKey和secretKey4.2 创建Bucket5.在SpringBoot中使用MinIO5.1 引入依赖5.2 配置文件定义5.3 定义实体类5.4 定义业务类5.5 定义测试类5.…

vivado中block design遇到的error总结

Error1.[BD 41-1356] Address block </processing_system7_0/S_AXI_HP0/HP0_DDR_LOWOCM> is not mapped into </axi_vdma_0/Data_MM2S>. Please use Address Editor to either map or exclude it. 修改方法. a、点击Address Editor. b、在Address Editor页面右击失…