观察者模式(Observer)

2023-11-08

一.观察者模式定义:

对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都得到通知并自动更新


二.观察者模式的结构说明:

1.Subject:目标对象

a.一个目标可以被多个观察者观察

b.目标可以提供添加和删除观察者,方便维护观察者

c.当目标的状态发生改变时,目标负责通知所有注册的,有效的观察者

2.Observer:定义观察者的接口,提供目标通知对应的更新方法,这个更新进行相应的业务处理


三.观察者模式的示例代码:

//Subject类

public class Subject {
	private List<Observer> observers=new ArrayList<Observer>();
	//注册观察者
	public void addObserver(Observer observer){
		observers.add(observer);
	}
	//删除观察者
	public void removeObserver(Observer observer){
		observers.remove(observer);
	}
	//通知所有的观察者
	public void nodifyAllObserver(){
		for(Observer observer:observers){
			observer.update(this);
		}
	}
}
//Observer接口

public interface Observer {
	public void update(Subject subject);
}


四.使用观察者模式的实现示例代码:

报社发布报纸,读者阅读报纸

//阅读者类

public class Reader implements Observer{//这个观察者是引入自己的观察者,不是引入jdk的观察者
	private String name=null;

	@Override
	public void update(Subject subject) {
		//收到通知后,回调目标的信息
		System.out.println(name+"收到报纸了,阅读它,内容是:"+((NewsPapper)subject).getContent());
	}
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
}
//报纸类

public class NewsPapper extends Subject{
	private String content=null;

	
	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
		
		//内容修改后,通知所有的监听者 
		this.nodifyAllReaders();
	}

}
//客户端测试

public class Client {
	public static void main(String[] args) {
		//创建阅读者
		Reader reader1=new Reader();
		reader1.setName("张三");
		Reader reader2=new Reader();
		reader2.setName("李四");
		Reader reader3=new Reader();
		reader3.setName("王五");
	
		NewsPapper papper=new NewsPapper();
		
		//注册阅读者
		papper.addReaders(reader1);
		papper.addReaders(reader2);
		papper.addReaders(reader3);
		
		//要出报纸啦
		papper.setContent("本期内容是观察者模式实例演示");
		
	}

}

五.简单模拟jdk实现的awt观察者模式:

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


//事件类  
class ActionEvent {  
        private long when;//事件发生的时间  
    private Object source;//事件源  
      
    public ActionEvent(long when, Object source) {  
        super();  
        this.when = when;  
        this.source = source;  
    }  
  
    public long getWhen() {  
        return when;  
    }  
  
    public Object getSource() {  
        return source;  
    }  
  
    public void setWhen(long when) {  
        this.when = when;  
    }  
  
    public void setSource(Object source) {  
        this.source = source;  
    }  
      
}  
  
//定义监听按钮的接口  
interface ActionListener {  
    public void actionPeformed(ActionEvent e);  
}  
  
//实现2个监听者  
class MyActionListener implements ActionListener {  
  
    @Override  
    public void actionPeformed(ActionEvent e) {  
        System.out.println("button pressed!!!");  
    }  
  
}  
  
  
class MyActionListener2 implements ActionListener {  
  
    @Override  
    public void actionPeformed(ActionEvent e) {  
        System.out.println("button pressed 2!!!");  
    }  
  
}  
  
//模拟按钮类  
class Button {  
    private List<ActionListener> actionListeners=new ArrayList<ActionListener>();  
    public void buttonPressed(){  
        for (ActionListener actionListener : actionListeners) {  
            actionListener.actionPeformed(new ActionEvent(System.currentTimeMillis(),this));  
        }  
    }  
    //注册监听者  
    public void addActionListener(ActionListener l){  
        actionListeners.add(l);  
    }  
      
}  
  
//测试  
public class Test {  
  
    public static void main(String[] args) {  
        Button b=new Button();  
          
        MyActionListener mal=new MyActionListener();  
        MyActionListener2 mal2=new MyActionListener2();  
        //注册监听  
        b.addActionListener(mal);  
        b.addActionListener(mal2);  
          
        b.buttonPressed();//发生按钮事件  
    }  
  
}


 

当然,jdk也提供了观察者模式,方便时,可直接查看jdk实现的观察者模式,鉴于是学习观察者模式,还是自己尝试着理解一下,方便以后复习

本文参考了《研磨设计模式》一书,以及马士兵老师的视频,特此声明!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

观察者模式(Observer) 的相关文章

  • 在 PHP 中比较两个对象的最快方法是什么?

    假设我有一个对象 在本例中为 User 对象 并且我希望能够使用单独的类来跟踪更改 用户对象不必以任何方式改变它的行为才能发生这种情况 因此 我的单独的类创建它的 干净 副本 将其存储在本地某个位置 然后可以将 User 对象与原始版本进行
  • 如何创建一个语句来打印以特定单词开头的单词? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 如何在 python 中打印从特定字母开始的单词 而不使用函数 而是使用方法或循环 1 我有一个字符串 想要打印以 m 开头的单词 S
  • Node.js - console.log 不显示数组中的项目,而是显示 [Object]

    我在注销对象内数组的内容时遇到问题 实际的物体看起来像这样 var stuff accepted item1 item2 rejected response Foo envelope from The sender to new item1
  • 隐式超级构造函数 Person() 未定义。必须显式调用另一个构造函数?

    我正在开发一个项目 但收到错误 隐式超级构造函数 Person 未定义 必须显式调用另一个构造函数 我不太明白它 这是我的人物课程 public class Person public Person String name double D
  • 具有字符串类型的 CAPL 关联数组

    按照此paper https kb vector com upload 551 file CAPL 3 CANNewsletter 201411 PressArticle EN pdf 我正在尝试创建一个像这样的关联数组 variables
  • 构造函数中显式关键字的使用

    我试图了解 C 中显式关键字的用法 并查看了这个问题C 中的explicit关键字是什么意思 https stackoverflow com questions 121162 但是 那里列出的示例 实际上是前两个答案 对于用法并不是很清楚
  • 如何使用JavaScript估算字符串的磁盘大小?

    我需要尝试估计DISKJavaScript 中文本字符串 可以是原始文本或图像 音频 等的 Base64 编码字符串 的大小 我不知道如何估计这个 当谷歌搜索时我唯一能找到的是 length所以我想 StackOverflow 上也许有人知
  • 来自另一个类的 Qt C++ GUI 调用

    我通过 gui 拖放创建了一个按钮和一个文本浏览器 UI 以及单击按钮功能是在 mainwindow cpp 中创建的 有一个 main cpp 但这是无关紧要的 因为在单击开始按钮之前程序不会启动 include mainwindow h
  • 在代码中旋转按钮(或其中的文本)

    我必须通过编码随机旋转按钮 或里面的文本 它是相同的 API级别低于11是否有button setRotate x 好吧 看了一下 答案是 很复杂 您可以使用旧的动画框架旋转按钮 例如像这样 Button button Button fin
  • 如何在qt中创建正确的退出按钮

    我正在尝试创建一个退出按钮来正确关闭我在 QT 中制作的 GUI 我尝试通过以下方式执行此操作 include
  • 使用 C# 动态创建按钮并按预定义的顺序放置它们

    NET 4 5 C 创建 Windows 窗体 我想动态创建和添加按钮并为其分配单击事件 但希望它们以特定的方式动态放置 就像图像一样 我的问题是如何以上述方式动态放置按钮 即 4x4 格式 一行 4 个按钮 4 列 但行数不受限制 是否可
  • 根据列中的部分字符串匹配选择数据框行

    我想根据列中字符串的部分匹配从数据框中选择行 例如列 x 包含字符串 hsa 使用sqldf if它有一个like语法 我会做类似的事情 select from lt gt where x like hsa 很遗憾 sqldf不支持该语法
  • setSize() 不起作用?

    我有一个程序 需要两个按钮 一个是常规按钮 另一个具有根据鼠标悬停而变化的图片 目前 由于图片很大 JButton自定义也很大 我可以更改自定义的大小并保持图像 和翻转图像 成比例吗 我尝试过 setSize 但它没有任何作用 对于任何反馈
  • 如何在Python中按字母顺序对字符串中的字母进行排序

    有没有一种简单的方法可以在Python中按字母顺序对字符串中的字母进行排序 So for a ZENOVW 我想返回 ENOVWZ 你可以做 gt gt gt a ZENOVW gt gt gt join sorted a ENOVWZ
  • Python 中的密码子生成

    我有这段代码 用于将 DNA 字符串转换为密码子列表 然后将此列表转换为具有各自氨基酸的字符串 然而 当我运行代码并且 DNA 字符串以一对核苷酸 例如 CT 而不是三联体结尾时 代码不会生成氨基酸序列 正如您在输出中看到的 from co
  • Python 3:将元组转换为字符串

    我有以下代码 var one var two var three 1 var one string one var 1 我需要对其执行以下操作 var four string two var one 但是 这会返回以下错误 TypeErro
  • 如何删除字符串中某个字符之后的所有内容?

    如何删除Python中字符串的某个字符之后的所有内容 例如 我有一个包含文件路径和一些额外字符的字符串 如何删除 zip 后的所有内容 我试过了rsplit and split 但在删除多余字符时都不包含 zip 有什么建议么 只需取出拆分
  • PHP 中的静态类初始值设定项

    我有一个带有一些静态函数的辅助类 类中的所有函数都需要一个 重 初始化函数来运行一次 就好像它是一个构造函数 有实现这一目标的良好实践吗 我唯一想到的就是打电话init函数 如果它已经运行过一次 使用静态 initialized变种 问题是
  • 如何从字符串中提取子字符串直到遇到第二个空格?

    我有一个像这样的字符串 o1 1232 5467 1232 5467 1232 5467 1232 5467 1232 5467 1232 5467 如何仅提取 o1 1232 5467 要提取的字符数并不总是相同 因此 我只想提取直到遇到
  • 在 C++ 代码中转换字符串

    我正在学习 C 并开发一个项目来练习 但现在我想在代码中转换一个变量 字符串 就像这样 用户有一个包含 C 代码的文件 但我希望我的程序读取该文件并插入将其写入代码中 如下所示 include

随机推荐

  • 1.7 起步 - 获取帮助

    1 7 起步 获取帮助 版本说明 版本 作者 日期 备注 0 1 loon 2019 3 19 初稿 目录 文章目录 1 7 起步 获取帮助 版本说明 目录 获取帮助 获取帮助 若你使用 Git 时需要获取帮助 有三种方法可以找到 Git
  • Vue中@click事件无效?@click.native中.native的含义和使用

    记录 click绑定事件的一个坑 问题描述 今天开发的时候 给组件绑定了 click事件 但是事件却没有执行 代码如下
  • 【Clion】自定义内容的自动补全——动态模板使用教程

    Clion的动态模板 动态模板的作用 实现自动补全 添加动态模板 添加动态模板的步骤 第一步是找到动态模板在哪里添加 打开clion的设置setting 找到编辑器选项editor 选择实时模板live template 选择C C 栏目
  • TCP协议疑难杂症全景解析

    说明 1 本文以TCP的发展历程解析容易引起混淆 误会的方方面面 2 本文不会贴大量的源码 大多数是以文字形式描述 我相信文字看起来是要比代码更轻松的 3 针对对象 对TCP已经有了全面了解的人 因为本文不会解析TCP头里面的每一个字段或者
  • Qt 主窗口与子窗口之间传值

    1 主函数向子函数传值 主窗口定义信号 子窗口定义槽函数 在主窗口将信号与槽连接起来 mainwindow h include
  • VTK笔记-使用vtkUnstructuredGrid类构建非结构化数据

    非结构化数据 非结构化点 非结构化点是在空间中离散随意分布的点 没有拓扑结构 几何机构也是完全没有规则的 非结构化点由顶点和多点的单元组成 非结构化点是一种简单但很重要的数据集类型 在部分可视化工作中会使用它来表示无结构的数据 非结构化网格
  • Windows Server 2019,开启多用户远程

    Windows Server 2019 开启多用户远程 最后记得重启计算机
  • DevopsCamp 第 2 期作业: 《cobra - 05 Cobra 的子命令》 简单说下 cobra 命令树和 gin 路由树的实现差异

    DevopsCamp 第 2 期作业 cobra 05 Cobra 的子命令 简单说下 cobra 命令树和 gin 路由树的实现差异 原文链接 https typonotes com posts 2023 02 14 devopscamp
  • PCL 体素滤波(C++详细过程版)

    体素滤波 一 概述 二 代码实现 三 结果展示 1 原始点云 2 滤波结果 一 概述 体素滤波PCL中经典的点云下采样算法 具体算法原理和实现代码见 PCL体素滤波器 为充分了解算法实现的每一个细节和有待改进的地方 使用C 代码对算法实现过
  • 力扣题---二叉树---相同的树

    题目连接 相同的树 首先我看题目要求以及例题 给你两棵二叉树的根节点 p 和 q 编写一个函数来检验这两棵树是否相同 如果两个树在结构上相同 并且节点具有相同的值 则认为它们是相同的 示例 1 输入 p 1 2 3 q 1 2 3 输出 t
  • FeignClient接口的几种方式总结

    FeignClient这个注解 已经封装了远程调用协议 在springboot的开发 或者微服务的开发过程中 我们需要跨服务调用 或者调用外部的接口 我们都可以使用FeignClient 一 FeignClient介绍 FeignClien
  • ChatGLM2-6B本地部署

    ChatGLM2 6B本地部署 ChatGLM2 6B 是开源中英双语对话模型 ChatGLM 6B 的第二代版本 在保留了初代模型对话流畅 部署门槛较低等众多优秀特性的基础之上 ChatGLM2 6B 引入了如下新特性 更强大的性能 基于
  • uniapp截取部分区域

    通过canvas来绘制截取部分 然后保存 html部分
  • 手把手教你,Selenium 遇见伪元素该如何处理?

    问题发生 在很多前端页面中 大家会见到很多 before after 元素 比如 百度流量研究院 比如 百度疫情大数据平台 以 百度疫情大数据平台 为例 累计确诊 文本并没有显示在 HTML 源代码中 如果通过常规的 xpath 元素定位方
  • Java 经典面试题:聊一聊 JUC 下的 LinkedBlockingQueue

    本文聊一下 JUC 下的 LinkedBlockingQueue 队列 先说说 LinkedBlockingQueue 队列的特点 然后再从源码的角度聊一聊 LinkedBlockingQueue 的主要实现 LinkedBlockingQ
  • c++中的关联容器

    c 中的关联容器主要是map set 已经multimap multiset 为了讲map 得先将pair类型 pair就是一个两个类型的组合 比如一个人的学号就可以是pair
  • 【重磅最新】163篇ICML-2021强化学习领域论文整理汇总(2021.06.07)

    深度强化学习实验室 官网 http www neurondance com 论坛 http deeprl neurondance com 作者 深度强化学习实验室 来源 整理自https icml cc ICML 是机器学习领域最重要的会议
  • 【python爬虫专项(25)】新型冠状病毒肺炎B站视频弹幕数据爬并做数据词云展示

    1 查看要爬取页面 打开B站网址 输入 新型冠状病毒肺炎 关键字 显示界面如下 2 确定爬虫逻辑 查看网页的内容后 一个网址页面下20个视频 这里只采集20页的视频数据 共400个视频 因为是出现的视频按照点击量进行排序的 所以再往后的视频
  • Java使用多线程异步执行批量更新操作

    写在前面 相信不少开发者在遇到项目对数据进行批量操作的时候 都会有不少的烦恼 尤其是针对数据量极大的情况下 效率问题就直接提上了菜板 因此 开多线程来执行批量任务是十分重要的一种批量操作思路 其实这种思路实现起来也十分简单 就拿批量更新的操
  • 观察者模式(Observer)

    一 观察者模式定义 对象间的一种一对多的依赖关系 当一个对象的状态发生改变时 所有依赖它的对象都得到通知并自动更新 二 观察者模式的结构说明 1 Subject 目标对象 a 一个目标可以被多个观察者观察 b 目标可以提供添加和删除观察者