设计模式 20 观察者模式

观察者模式(Observer Pattern)属于 行为型模式

在 Java 中,一个对象的状态发生改变,就可能会影响到其他的对象,与之相关的对象可能也会联动的进行改变。

比如监听器机制,当具体的事件触发时,可以在创建的监听器中执行相关的逻辑。

观察者模式可以实现这样的功能,当对象发生改变时,观察者能够立即观察到并进行一些联动操作。

自定义实现

这里以监听主体改变为例来介绍观察者模式:

1、定义观察者

/**
 * 观察者
 */
public interface Observer {

    /**
     * 更新操作
     */
    void update();

}

2、定义观察者实现类

/**
 * 观察者实现类
 */
public class ObserverImpl implements Observer {

    @Override
    public void update() {

        System.out.println("进行了修改");
    }
}

3、定义主体

/**
 * 主体
 */
public class Subject {

    /**
     * 观察者集合
     */
    private final Set observerSet = new HashSet<>();

    /**
     * 添加观察者
     * @param observer 观察者
     */
    public void observe(Observer observer) {
        observerSet.add(observer);
    }

    /**
     * 修改
     */
    public void modify() {

        // 当对象发生修改时,会通知所有的观察者,并进行方法回调
        observerSet.forEach(Observer::update);
    }

}

4、调用

// 主体
Subject subject = new Subject();
// 添加观察者
subject.observe(new ObserverImpl());
// 修改
subject.modify();

输出结果为:

&#x8FDB;&#x884C;&#x4E86;&#x4FEE;&#x6539;

可以发现,当主体调用修改方法时,添加的观察者观察到了变化,执行了操作。这就是观察者模式的自定义实现。

JDK自带实现

JDK 也提供了实现观察者模式的方式:

1、定义 JDK 实现的观察主体

/**
 * JDK实现的观察主体
 * 继承 Observable 表示支持观察者
 */
public class Subject4Jdk extends Observable {

    /**
     * 修改
     */
    public void modify() {

        System.out.println("进行了修改");
        // 当对象修改后,需要 setChanged 来设定为已修改状态
        this.setChanged();
        // 使用 notifyObservers 方法来通知所有的观察者
        // 注意只有已修改状态下通知观察者才会有效,并且可以给观察者传递参数,这里传递了一个时间对象
        this.notifyObservers(new Date());
    }

}

2、调用

// 主体
Subject4Jdk subject4Jdk = new Subject4Jdk();
// 添加观察者(Observable提供的方法)
subject4Jdk.addObserver((o, arg) -> System.out.println("监听到变化,并得到参数:" + arg));
// 进行修改操作
subject4Jdk.modify();

输出结果为:

&#x8FDB;&#x884C;&#x4E86;&#x4FEE;&#x6539;
&#x76D1;&#x542C;&#x5230;&#x53D8;&#x5316;&#xFF0C;&#x5E76;&#x5F97;&#x5230;&#x53C2;&#x6570;&#xFF1A;Tue Aug 16 21:32:43 CST 2022

可以发现,JDK 自带的实现方式更为简洁,且功能更为强大,还能传递参数。

1、观察者和被观察者是抽象耦合的。

2、建立一套触发机制。

1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

1、一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。

2、一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。

3、一个对象必须通知其他对象,而并不知道这些对象是谁。

4、需要在系统中创建一个触发链,A 对象的行为将影响 B 对象,B 对象的行为将影响 C 对象……,可以使用观察者模式创建一种链式触发机制。

1、Java 中已经有了对观察者模式的支持类。

2、避免循环引用。

3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

Original: https://www.cnblogs.com/codesail/p/16593096.html
Author: 程序航
Title: 设计模式 20 观察者模式

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/715017/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • JAVA8-Lambda-List转Map

    List转Map需要注意点是在收集map时Collectors.toMap()建议选三个入参的方法。 示例如下:(注意list中的”张三”有两个我们将其作为…

    技术杂谈 2023年7月24日
    063
  • SpringBoot 项目部署 (配置文件分离)

    SpringBoot 配置文件加载 SpringBoot 加载配置文件的优先级如下: 当前目录下的 config 子目录; 当前目录; classpath下的 config文件夹;…

    技术杂谈 2023年6月21日
    0120
  • Vue组件介绍

    #基本示例 Vue组件的定义: component (组件)中的data ,必须是个函数,这是因为 组件是需要复用的,每次的复用,都相当于创建了一个新的实例. 这种情况跟 类(ja…

    技术杂谈 2023年7月11日
    074
  • jvm的简介

    什么是jvm? java虚拟机就是二进制字节码的运行环境。我们可以把jvm看做是运行在不同系统上的一个软件应用的计算机,就比如说我们要打开图片,就得用看图软件,或者我们要对文件进行…

    技术杂谈 2023年7月11日
    096
  • Java基础学习笔记(2)

    二、流程控制 1、用户交互Scanner java.util.Scanner是Java5的新特性, 我们可以通过Scanner类来获取用户输入。 *基本语法: Scanner s …

    技术杂谈 2023年7月24日
    080
  • MQ详解

    什么是MQ? 【1】MQ:MessageQueue,消息队列。 队列,是一种FIFO 先进先出的数据结构。消息由生产者发送到MQ进行排队,然后按原来的顺序交由消息的消费者进行处理。…

    技术杂谈 2023年7月24日
    072
  • ES基本查询语句教程

    前言 es是什么? es是基于Apache Lucene的开源分布式(全文)搜索引擎,,提供简单的RESTful API来隐藏Lucene的复杂性。 es除了全文搜索引擎之外,还可…

    技术杂谈 2023年6月1日
    0118
  • crudapi增删改查接口零代码产品成功案例之金茶王投票系统

    crudapi增删改查接口零代码产品成功案例之金茶王投票系统 简介 2020年由于疫情原因,金茶王投票活动改成线上云投票,所以需要一套投票系统进行比赛。参赛选手包括两种类型,分别为…

    技术杂谈 2023年7月24日
    064
  • assetBundle 中的prefeb资源图片显示粉色方框

    assetBundle打包的资源是有平台属性的,当移动端iOS或者Android AssetBundle资源 在editor 加载的时候,比如TextMeshPro中的字体就不能正…

    技术杂谈 2023年5月30日
    0109
  • Excel中*替换为空

    查找输入~*替换不输入全部替换将 * 这个替换成空白 Original: https://www.cnblogs.com/gisoracle/p/16309234.htmlAuth…

    技术杂谈 2023年5月30日
    0104
  • 成大事者,必精读也!!!

    一:沉稳 (1)不要随便显露你的情绪。 (2)不要逢人就诉说你的困难和遭遇。 (3)在征询别人的意见之前,自己先思考,但不要先讲。 (4)不要一有机会就唠叨你的不满。 (5)重要的…

    技术杂谈 2023年7月23日
    069
  • 面试手撕并发算法题

    固定打印顺序 使用 wait-notify 实现以下功能:先打印 b,再打印 a 线程t1和t2同时运行,t1中打印 a,t2中打印 b,但 t1 打印得有个前提,就是 t1要在t…

    技术杂谈 2023年6月21日
    075
  • String和List相互转换

    1,String转List csharp;gutter:true; //常见的为逗号分隔 String str = "a,b,c"; List list1 = …

    技术杂谈 2023年5月31日
    082
  • WSL简单环境搭建以及踩坑

    笔者的电脑配置不高,开虚拟机跑linux总觉得太重。最近才了解到windows早就上了wsl2——一款较为轻量的虚拟机软件。所以笔者打算一边安装一边记录笔记,方便以后查阅,同时将内…

    技术杂谈 2023年6月21日
    086
  • “OneNote由于某种原因,无法连接到服务器。请尝试检查您的连接以查看服务器是否可用。”的解决方案

    最近开始新的学习生活,使用OneNote做笔记。作为一个强迫症,无法创建新的笔记的问题让我很是难受。在这里看到了一个解决的方法→解决办法 更改DNS:1.打开控制面板-网络共享中心…

    技术杂谈 2023年7月10日
    090
  • [学习笔记]Java异常处理

    程序运行时,可能会发生各种错误,一些错误是可以避免的,还有些错误是随机出现的且不可避免,一个健壮的程序必须能够处理这些错误; Java内置一套异常处理机制,使用异常来表示错误; 异…

    技术杂谈 2023年7月24日
    070
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球