初探Java设计模式------观察者模式

article/2025/9/10 16:40:32

前言

最近刚开始学习RxJava,众所周知,Rxjava就是扩展的观察者模式,所以想学习Rxjava,先入手了解一下观察者模式是很有必要的。那么今天就先稍微了解一下什么是观察者模式。

定义

 观察者(Observer)模式:是对象的行为模式,也叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Module/View)模式、源-监听(Source/Listener)模式或者从(Dependents)模式。观察者模式定义了一对多的依赖关系,即让多个观察者对象同时监听同一个主题对象,当这个主题对象的状态发生改变时,要通知所有的观察者对象,使他们能够更新自己。

!

众大神博客里面最多的例子就是天气预报和小偷警察的例子。拿小偷和警察的例子来说,小偷就是被观察者,而警察就是观察者。多个警察在关注小偷的行为,当小偷想偷东西时,即主题对象状态发生改变时,这个时候很多警察就会上去抓住他,也就是观察者更新了自己的行为。

UML类图

Paste_Image.png
我们来解释一下UML图中的含义:

Subject
主题,即被观察者接口,它是一个抽象的接口,包含三个方发,attach()即增加订阅者,detach()删除订阅者,notifyObserver()通知订阅者;
Observer
观察者接口,它是一个抽象的接口,其中含有一个update()方发,用来在被观察者状态改变的时候进行更新自己。
ConcreteSubject
被观察者对象,实现了被观察者接口,同时有一个List集合,用以保存注册的观察者,等需要通知观察者时,遍历该集合即可。 注意,该集合的泛型参数应该是Observer,接口类型,而不应该是具体的Observer实现类,这样做的原因是一个被观察者可能会有多个不同实现类的观察者(但都实现了Observer接口),如果限定了某一个具体的类型,那么会导致以后要加入新类型的时候而不得不修改当前类,耦合度过高,这是一个非常不好的行为。
ConcreteObserver
实现了update()方法。

实现步骤

1.建立接口和抽象类

public interface Observer {    public String getmName();    void update(String weather);
}
public abstract class Subject {    //保存观察者的集合    public List<Observer> observers=new ArrayList<Observer>();    /**     * 添加观察者    * @param observer     */    public void attach(Observer observer){        observers.add(observer);        System.out.println(observer.getmName()+"订阅天气预报");    }    /*** 移除观察者    */    public void detach(Observer observer){observers.remove(observer);System.out.println(observer.getmName()+"取消订阅天气预报");   }  /**     * 通知所有的观察者改变状态    */    public void notifyObservers(String weather){        for(Observer observer:observers){            observer.update(weather);       }    }}

2.实现观察者接口

public class ObserserPeople implements Observer {    private String mName;    public ObserserPeople(String name){        this.mName=name;    }    
public void update(String weather) {        System.out.println(mName+"收到天气预报消息"+weather);    }    
public String getmName() {        return mName;   }}

3.继承被观察者抽象类

public class WeatherSubject extends Subject {    public void change(String weather){        notifyObservers(weather);   }}

这样我们就写完了,下面我们编写一个测试类:

public class Test {    public static void main(String[] args) {        Observer observer=new ObserserPeople("校长");        Observer observer2=new ObserserPeople("主任");        Observer observer3=new ObserserPeople("老师");        WeatherSubject subject=new WeatherSubject();        subject.attach(observer);        subject.attach(observer2);        subject.attach(observer3);        subject.change("下个周即将下雪!!!");        subject.detach(observer3);        subject.change("下周不下雪了!");    }}

输出结果如下:

校长订阅天气预报
主任订阅天气预报
老师订阅天气预报
校长收到天气预报消息下个周即将下雪!!!
主任收到天气预报消息下个周即将下雪!!!
老师收到天气预报消息下个周即将下雪!!!
老师取消订阅天气预报
校长收到天气预报消息下周不下雪了!
主任收到天气预报消息下周不下雪了!

通过上面例子,可以看出,当观察者订阅了被观察者时,被观察者改变立马会通知观察者,观察者就会执行update()方法。当然,我在这里没有做实现。具体可以更具业务逻辑来进行实现。


http://chatgpt.dhexx.cn/article/E0VJLxec.shtml

相关文章

java设计模式(3)--观察者模式

&#xff08;一&#xff09;观察者模式 观察者模式定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。 该模式有以下角色&#xff1a; &#xff08;1&#xff09;抽象主题&#xff08;Subjec…

Java设计模式之行为型:观察者模式

一、什么是观察者模式&#xff1a; 观察者模式又称为 发布-订阅模式&#xff0c;定义了对象之间一对多依赖关系&#xff0c;当目标对象(被观察者)的状态发生改变时&#xff0c;它的所有依赖者(观察者)都会收到通知。一个观察目标可以对应多个观察者&#xff0c;而这些观察者之间…

java监听设计模式(java观察者设计模式)

今天给大家分享一下观察者设计模式&#xff08;监听设计模式&#xff09;&#xff0c;该模式在很多主流得框架、源码中使用率非常高。在分享之前先给大家讲一个我们使用手机的一个场景&#xff0c;我们都用过手机&#xff0c;当我们手机来电话的时候&#xff0c;会有各种复杂的…

【十一】设计模式~~~结构型模式~~~代理模式(Java)

【学习难度&#xff1a;★★★☆☆&#xff0c;使用频率&#xff1a;★★★★☆】 6.1. 模式动机 在某些情况下&#xff0c;一个客户不想或者不能直接引用一个对 象&#xff0c;此时可以通过一个称之为“代理”的第三者来实现 间接引用。代理对象可以在客户端和目标对象之间起…

JAVA架构之路(设计模式之观察者模式)

设计模式之观察者模式 定义&#xff1a;对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新 核心原理&#xff1a; 1.被观察者中维护一个观察者对象列表 2.观察者可新增可可移除。 需要角色&#…

程序员百宝箱---搭建自己专属的在线工具集

相信各位开发者/程序员在开发过程中都使用过各种在线工具吧。比如 1 校验或格式化 json 字符串 2 使用 base64 的加密解密&#xff0c;url 的编码解码 urlencode、urldecode 等 3 调试正则表达式是否正确 4 时间戳与格式化日期互相转换 5 文本对比&#xff0c;比较两个代码文件…

如何部署JSP应用到阿里云服务器上(一)

今天讲解一下如何部署JSP应用到阿里云服务器上&#xff0c;我使用的后台服务器是 Tomcat服务器&#xff0c;服务器应用的开发语言是 Java Web &#xff0c;后台的数据库使用的是MySQL 1 打开阿里云官方网站 https://www.aliyun.com/?utm_mediumtext&utm_sourcebdbrand&am…

开源项目精选推荐-杨小杰工具箱(YoungxjTools)

演示 预览地址: https://tools.yum6.cn/ 程序介绍 01、首页底部友情链接 02、网站公告页面功能 03、内置留言管理功能 04、后台网站信息设置 05、内置smtp发信配置 06、支持两主题的切换 07、关于页面支持留言, 08、程序已集成32种小工具 更多功能 介绍 请搭建 自行测试

C++构造函数之初始化列表

C构造函数之初始化列表 构造函数可以说是对于C每个类来说最重要的组成部分&#xff0c;之前也详细介绍过构造函数的相关知识&#xff0c;今天给构造函数进行补充&#xff0c;主要说明一下构造函数的初始值列表 一、初始化列表的写法 仍然以之前介绍构造函数时使用的学生类来…

C++初始化列表详解

目录&#xff1a; 定义 使用初始化列表的原因 必须使用初始化列表的时候 成员变量的顺序 定义 与其他函数不同&#xff0c;构造函数除了有名字&#xff0c;参数列表和函数体之外&#xff0c;还可以有初始化列表&#xff0c;初始化列表以冒号…

C++类的初始化列表

意义 初始化列表是类中构造函数的一部分&#xff0c;用于实例化类中变量时 赋初值。 需要先了解 构造函数的基本知识。CSDN-构造函数https://blog.csdn.net/weixin_44212838/article/details/124901019?spm1001.2014.3001.5501 用法 在函数头与函数体之间&#xff0c;用一…

详解初始化列表

初始化列表 定义 构造函数有个特殊的初始化方式叫“初始化表达式表”&#xff08;简称初始化列表&#xff09;。初始化列表位于函数参数表之后&#xff0c;却在函数体 {} 之前。这说明该表里的初始化工作发生在函数体内的任何代码被执行之前。 Date(int year, int month, in…

C++ 成员初始化列表

这里写目录标题 数据成员是某一个类的对象&#xff0c;且这个类没有默认构造函数数据成员的类型是const或者引用子类初始化父类初始化列表先后顺序使用成员初始化列表的优点 在以下三种情况下需要使用初始化成员列表&#xff1a; 需要初始化的数据成员是某一个类的对象&#xf…

【深入理解】初始化列表

目录 一、什么是初始化列表&#xff1f; 二、初始化列表长啥样&#xff1f; 三、初始化列表的特性 1、由于是在定义阶段进行的初始化&#xff0c;所以&#xff0c;只能在定义阶段进行的初始化类型便只能在初始化列表中进行初始化。 2、初始化顺序不是跟着初始化列表走的&#x…

C++ 初始化列表详解

目录 1.什么是初始化列表 2.什么时候需要使用初始化列表&#xff1f; 3.初始化列表的效率 4.初始化列表的初始化顺序 1.什么是初始化列表 class A { public:A(int value):m_dada(value){}private:int m_dada; }; 如上图&#xff0c;红色圈起来的部分&#xff0c;就是构造函…

【C++】-- 初始化列表

目录 一、用初始化列表初始化对象 1.初始化列表用法 2.初始化列表特性 二、explicit关键字 1.内置类型的隐式转换 2.如何避免单参构造函数初始化发生隐式类型转换 三、匿名对象 1.匿名对象定义 2.匿名对象应用场景 创建一个类对象时&#xff0c;编译器通过调用构造函…

字符串逆序(数组倒序输出)

题目信息&#xff1a; 样例输出 copy edcba 新手导读&#xff1a; 题目描述信息&#xff1a;字符串的倒序输出肯定是字符数组的倒序输出&#xff1b; 输入信息&#xff1a;输入条件是最后字符不为回车&#xff1b;所以应该先用变量存入字符进行判断&#xff0c;再使用这个…

C语言实现字符串倒序

C语言显示字符串倒序 倒序字符串的方法很多&#xff0c;这里给出常见的两种 1.倒序字符串指针法 void reverse_string(char *arr) {int len strlen(arr);char* left arr; //指向头部的指针char* right arr (len - 1); //指向尾部的指针char temp;while(left <…

C语言:输入一串字符串,并倒序输出(vs)

一&#xff1a;问题&#xff1a; 输入一串字符串倒序输出 例&#xff1a;输入abcdefg 输出gfedcba 二&#xff1a;思路&#xff1a; &#xff08;1&#xff09;先输入一串字符串&#xff0c;然后利用for语句倒序输出即可&#xff1b; 三&#xff1a;实现过程&#xff1a; …

字符串倒序输出

题目&#xff1a;输入一个字符串&#xff0c;将该串倒序输出。例如输入字符串hello&#xff0c;倒序输出为olleh。 str1 str(input(请输入字串: )) print(输入的字符是&#xff1a;%s%str1) str2 #定义一个空串用来接收倒序后的字串 for i in str1[::-1]:#对字串进行倒序输出…