记录开发中使用的设计模式之发布订阅者模式(观察者模式)

2023-10-29

一、开发场景

当我们在开发中涉及到大量的调用跨应用API的时候,需要按照场景书写大量的重复性代码,常规的做法就是通过if/else进行场景判断,进行调用,代码十分的冗余,重复性的调用方法,不利于后期的维护,而为了更好的针对某些场景,去调用对应的API,可以使用发布订阅者模式更好的管理相关接口

二、订阅/发布者模式简介

观察者(Observer)模式又名发布-订阅(Publish/Subscribe)模式。GOF 给观察者模式如下定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依 赖于它的对象都得到通知并被自动更新。

三、代码案例(UML图)

在这里插入图片描述

四、业务代码实现

注意:该设计模式是贴近业务场景的代码,不是原生的设计模式模板,已做了相关改动

  1. 事件发布者Publisher
package com.CmJava.Desginer;

/**
 *  事件的发布者
 *   通知事件
 */
public class Publisher {
    // 发布事件 类型
    String event;

    // 发布的消息
    String msg;

    private String getEvent() {
        return event;
    }

    private void setEvent(String event) {
        this.event = event;
    }

    private String getMsg() {
        return msg;
    }

    private void setMsg(String msg) {
        this.msg = msg;
    }

    /**
     *  事件发布操作
     * @param event
     * @param msg
     */
    public void publish(String event, String msg){
        this.event = event;
        this.msg = msg;
    }

    /**
     * 通知订阅者
     */
    public void NotifyPublisher(){
        System.out.println("===消息发布===");
        ActuatorFactory.sync(event,msg);
    }
}

  1. 订阅者抽象类Subscriber
package com.CmJava.Desginer;

public abstract class Subscriber {

    // 订阅事件
    String event;

    public Subscriber(String event) {
        this.event = event;
    }

    // 处理方法
    public void handle(String msg){
        System.out.println("订阅消息:开始处理 。。。。"+msg);
    }
}

  1. 具体的订阅者,这里我们举两个操作的例子SaveSubscriber
package com.CmJava.Desginer;

public class SaveSubscriber extends Subscriber {


    public SaveSubscriber(String event) {
        super(event);
    }

    @Override
    public void handle(String msg) {
        super.handle(msg);
        System.out.println("SaveSubscriber 接收到:"+event);
        System.out.println("执行保存操作");
    }
}

SubmitSubscriber

package com.CmJava.Desginer;

public class SubmitSubscriber extends Subscriber {


    public SubmitSubscriber(String event) {
        super(event);
    }

    @Override
    public void handle(String msg) {
        super.handle(msg);
        System.out.println("SubmitSubscriber 接收到:"+ event);
        System.out.println("执行提交操作");

    }
}

  1. 事件注册类 TopicRegister

该类用于区分,具体事件的订阅者

package com.CmJava.Desginer;

/**
 *  事件注册类
 */
public class TopicRegister {
    // 注册事件类型
    String event;

    // 注册订阅者
    Subscriber subscriber;

    public String getEvent() {
        return event;
    }

    public void setEvent(String event) {
        this.event = event;
    }

    public Subscriber getSubscriber() {
        return subscriber;
    }

    public void setSubscriber(Subscriber subscriber) {
        this.subscriber = subscriber;
    }

    public TopicRegister(String event, Subscriber subscriber) {
        this.event = event;
        this.subscriber = subscriber;
    }
}

  1. 执行工厂方法ActuatorFactory

用于处理,事件发布,去通知订阅者的工厂方法

package com.CmJava.Desginer;

import java.util.*;

public class ActuatorFactory {

    private static final List<TopicRegister> list = new ArrayList<>();

    static {
        list.add(new TopicRegister("save",new SaveSubscriber("save")));
        list.add(new TopicRegister("submit",new SubmitSubscriber("submit")));
    }

    /**
     *  事件处理
     * @param event
     * @param msg
     */
    public static void sync(String event,String msg){
        for (TopicRegister register : list) {
            if (register.getEvent().equals(event)){
                Subscriber subscriber = register.getSubscriber();
                subscriber.handle(msg);
            }
        }
    }


}

  • 测试类
package com.CmJava.Desginer;

public class MainTest {
    public static void main(String[] args) {
        Publisher publisher = new Publisher();
        System.out.println("===第一次消息发布===");
        publisher.publish("save", "需要保存数据,,,");
        publisher.NotifyPublisher();
        System.out.println();
        System.out.println("===第二次消息发布===");
        publisher.publish("submit", "需要提交数据,,,");
        publisher.NotifyPublisher();
    }
}

五、测试运行结果

在这里插入图片描述

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

记录开发中使用的设计模式之发布订阅者模式(观察者模式) 的相关文章

  • BPMN的优点和缺点?

    我希望您能告诉我从开发人员的角度来看 BPMN 的优点和缺点是什么 我将 UML 与 BPMN 进行比较 发现 UML 有很多优点和缺点 但 BPMN 却没有 这很大程度上取决于观众和目的 在建模语言方面 BPMN 和 UML 活动图涵盖了
  • 子集约束在 UML 类图中意味着什么

    有subset在部门类和人员类之间 但我不知道比是什么意思 家庭作业机会 查看由子集约束链接的两个关系 每个部门有多名成员 每个部门设经理一名 子集表示这两者之间的约束 如果后一个关系的元素是第一个关系的子集 那么你会如何描述其含义 EDI
  • 如何使用用例关系 - uml

    嘿伙计们 我一直在研究 UML 并且正在尝试设计问题的用例图 假设我的应用程序包含以下内容 两个要求 创建团队 创建玩家 这是这笔交易 用户可以创建一个球队 创建球队后可以为该球队创建球员 非必需 但在这个应用程序中有多个用户 一个用户可以
  • 如何在重写方法中表示调用基类方法?

    我有一个子类想要向基类函数添加更多功能 我如何表示它也执行基类函数而不仅仅是新添加的功能 有趣的问题 我用 Enterprise Architect 尝试过 它确实让我选择了父级的操作 但图中的显示没有改变 看来您需要为此使用注释 如你看到
  • 如何绘制java uml类图并在另一个类中创建枚举[重复]

    这个问题在这里已经有答案了 假设我有一个类名 A 在这个类中我定义了枚举 Bpublic enum B AA BB CC 现在我想画一个uml来体现这种关系 应该怎么做呢 在类类图中 表示使用 例如
  • uml 与 RDF 和 OWL 的组合关系

    我是 RDF 和 OWL 本体的初学者 我正在尝试将此图转换为 OWL 语法
  • 如何在 UML 活动图上显示异步操作

    我即将绘制 记录一些客户端 服务器连接建立代码 以更好地理解它 有几个操作是在单独的线程中异步完成的 连接线程 数据接收线程等 我应该在单独的图表上显示它们吗 我更愿意将其放在单个图表上以掌握整体视图 但不知道如何在活动图上表示它 我不确定
  • staruml 抽象类?

    有谁知道如何使用 StarUML 创建抽象类 我在文档中找不到任何提及 是否有某种反映抽象类的更一般的概念 从工具箱中选择类并将其添加到画布中 然后转到属性选择 isAbstract 复选框 然后类名显示为斜体
  • XMI 2.1.1 的 XSD

    我必须使用 JAXB 解析 XMI 文件 xmi 版本 2 1 1 为此 我必须生成与 XMI 文件相对应的 Java 类 因此 我需要 xmi 文件的 shema 定义才能使用 jxc 工具执行此操作 我希望有人知道在哪里可以找到这个文件
  • 如何用序列图来展示一个类与另一个类之间的关系,以该类的实例的实例作为输入?

    我将使用之前的相同示例question https stackoverflow com questions 66934927 how to represent the relationship between an instance of
  • 关联注入还是依赖注入?

    我正在研究依赖注入模式 我看过很多例子 其中一个典型的例子就是以XxxService XxxRepository为例 但我认为 根据UML概念 类XxxRepository应该是类XxxService的关联 为什么不称这种情况为关联注入 但
  • Dia:图表编辑器:盒子对象的限制?

    如标题所示 我尝试为 hte 3d 图形引擎 ogre3d 开发尽可能少的方案 问题是大图方案 Ogre Root 类需要相当多的从它下降的箭头 用关系箭头连接框的模型是它们只能通过边界周围的特定点 称为 关节 或其他东西 进入 退出 但现
  • 是否可以在 UML 中可视化一堆函数

    我正在改进一个使用类和函数文件 只是包含各种函数的 php 文件 的内容管理系统 例如 我有一堂课叫Admin以及一个功能文件 其功能包括显示管理员概述 创建新管理员 编辑现有管理员 删除管理员 函数文件使用类并执行 mvc 概念的可视化部
  • 不同保护条件下的状态转换

    在状态模式中这是如何建模的 当当前状态为 A 时 在触发器 X 和条件 C1 上状态 A 到状态 B 当当前状态为 A 时 在触发器 X 和条件 C2 上状态 A 到状态 C 这通常是如何实现的 我有很多可能需要实施的守卫条件 这是相当标准
  • Android Studio 上的代码 Iris 插件

    我正在尝试使代码 iris 插件在 Android studio 上工作 我按右键单击 gt 创建代码虹膜图 然后我收到一条通知 表明我的图表已准备就绪 但我不知道该图何时存储 创建的文件的名称是什么以及如何打开它 有任何想法吗 CODE
  • 创建UML图时应该编写构造函数吗?

    我有一项作业要求我为实际的 Java 程序创建 UML 图 但程序中有几个构造函数方法 我很困惑 我是否应该将这些构造函数方法添加到图中 根据 UML 规范 2 5 版第 11 4 4 节 构造函数是一个具有所属类类型的单个返回结果参数的操
  • UML:一对多关系表示?

    我是 UML 新手 还不太理解其表示法 这是我对图的理解 The system has many doctors Doctors can have many patients however patients can only have o
  • 用例图的本质

    对于学校作业 我们必须制作用例图 但我们拥有的文档并不是很丰富 它仅描述用例由哪些组件组成 以及一个示例 我们必须制作一个关于图书馆系统的用例 我们已经找到了 11 个用例 但我不会用所有用例来打扰您 IIRC 用例描述了系统的典型用法 对
  • UML 中的 IsRoot、IsAbstract 和 IsLeaf 何时使用?

    我遇到了以下描述IsRoot IsAbstract IsLeaf但不明白你什么时候会使用它们 摘自http www2 sys con com itsg virtualcd dotnet archives 0108 clark index h
  • [GoF]-ConcreteSubject 可以覆盖通知方法吗?

    我正在模拟一种情况 其中存在 通知框 观察者 list1 list2 list3 这个科目 现在我会制作一张图表 其中使用观察者模式描述每个列表实现不同类型的notify 这一事实 例如 列表状态的某些变化只需要按照某些标准通知给某些观察者

随机推荐

  • 在NW.js里面使用node-printer

    0 写在前面的一些提示 不要使用太高版本的 NW js 以及 Node js 因为 node printer 会有兼容性问题 目前笔者测试到 node printer 最高只能在 0 43 x 版本以及低于这个版本的 NW js 里面正常运
  • 代码走查与代码审查区别

    代码走查 程序员和测试员组成审查小组 通过逻辑运行程序 第一步 小组成员提前阅读设计规格书 程序文本等相关文档 第二步 利用测试用例 使程序逻辑运行 记录程序的踪迹 发现 讨论 解决问题 代码审查 程序员和测试员组成审查小组 第一步 小组成
  • robot通过一个元素定位另一个元素

    xpath定位 xpath span text 文章评为精华 div div span text 去完成
  • 一些keil编程错误总结

    一 error c267 delay 10us requires ANSI style prototype问题 解决方法 1 未进行 模块化程序设计时 delay 10us该子函数要在主函数前 2 在进行 模块化程序设计时 这是由于 c文件
  • 区块链在非金融领域有哪些值得期待的应用

    引言 自己关注区块链好多年了 感觉大部分人都在炒币 或者所谓的搞金融 但是现在各国的审查都越来越严格 针对金融领域的审查尤其严格 在国内 基本上是禁止区块链应用有任何的发币行为的 我个人也是觉得金融领域的监管太多 反而不容易落地 这篇文章来
  • Redis中的String类型与List类型个人理解

    String类型 String类型是Redis的最基础类型 最大能存储512MB 其中存储值可以是最简单的字符串 复杂的 xml json的字符串 二进制图像或者音频的字符串 以及是数字的字符串 String数据类型与结构 基本操作 set
  • R语言的plyr包简介

    转载地址 http www jianshu com p bfddfe29aa39 R语言的plyr包简介 字数3040 阅读2875 评论3 喜欢7 R语言中的类SQL操作 plyr包可以进行类似于数据透视表的操作 将数据分割成更小的数据
  • Eclipse启动tomcat出现invalid ports的解决办法

    在Eclipse出现以上错误的 可以继续往下看 在server中 点击Tomcat 进入设置 把三个端口都填写了不留空 根据情况来填写相应的端口号 防止占用 保存即可
  • 交易流水指标统计——pandas

    1 根据交易流水 计算每个交易交易对象的如下指标 总收入笔数 总收入月数 最大月收入笔数 最大月收入笔数所在日期 年月日格式 import pandas as pd path r C Users xxx Desktop 科技数据 xlsx
  • Angular入门学习笔记

    Angualr入门扫盲必备 声明 这篇是我学习angualr的笔记 可以转载 但必须注明来源作者 kone 并附上本文链接 A 环境 工具 1 先确保安装了nodejs和npm Nodejs npm 包管理器 cnpm 淘宝的镜像 2 安裝
  • 低代码让开发变得不再复杂

    传统IT自研软件开发 通过编程去写代码 还有数据库 API 第三方基础架构等 从而造成开发周期长 难度大 技术人员不易于开发维护 因此价格及时间成本也是相对较高 后期出现了可以直接应用的成品软件 以及现在火热的低代码开发方式 针对这三种方式
  • 给Sqlite数据库设置密码

    免费版Sqlie是不提供设置密码功能的 经过查阅资料最终找到了解决方案 方案一 从sqlite源码入手 据说sqlite源码已经提供了加密的接口 只是免费版没有实现 可以参考这位仁兄的博客以了解详情 http www cnblogs com
  • 架构师是做什么的?

    哈佛大学有一个非常著名的关于目标对人生影响的跟踪调查 调查的对象是一群智力 学历 环境等条件都差不多的大学毕业生 结果是这样的 第一类人 27 的人 没有目标 第二类人 60 的人 目标模糊 第三类人 10 的人 有清晰但比较短期的目标 第
  • Mysql错误1452 - Cannot add or update a child row: a foreign key constraint fails 原因及解决方法

    报错的原因大概分为三种 原因一 添加的外键列与另一个表的唯一索引列 一般是主键 的数据类型不同 原因二 要添加外键的表类型与另一个表的存储引擎是不是都为innodb引擎 查看表引擎 法一 show create table 表名 法二 sh
  • ag-grid在Vue项目中的基本使用

    ag grid官网 1 安装 npm install ag grid community ag grid vue save dev 2 在main js中引入ag grid的样式文件 引入ag grid的样式文件 import node m
  • bing搜索引擎入口_资源搜索,除了百度,还有哪些好用的搜索引擎?

    作者 杨银洁 来源 ETPPT 遇到问题怎么办 百度一下 你out了 除了百度还有很多搜索引擎 而且还有很多国外网站可以检索哦 是否还在苦恼高清图找不到 PPT素材找不到 关注ETPPT这些就不是问题 今天我们就介绍一下有哪些可以轻松帮助你
  • 云原生之使用Docker部署BookBrowser电子书浏览器

    云原生之使用Docker部署BookBrowser电子书浏览器 一 BookBrowser简介 1 BookBrowser简介 2 BookBrowser特点 二 检查docker环境 1 检查docker状态 2 检查docker版本 3
  • Java线程和操作系统线程的关系

    传统进程的缺点 fork一个子进程的消耗是很大的 fork是一个昂贵的系统调用 即使使用现代的写时复制 copy on write 技术 各个进程拥有自己独立的地址空间 进程间的协作需要复杂的IPC技术 如消息传递和共享内存等 多线程的优缺
  • 【C++从入门到放弃】C++编译生成动态链接库*.so及如何调用*.so进阶篇2-编译jsoncpp

    C 从入门到放弃 C 编译生成动态链接库 so及如何调用 so进阶篇2 编译jsoncpp 附 当前项目cstudy7 本文可以收获什么 将其它项目生成的动态链接库拿到本项目中使用 CMakeLists txt中使用其它项目的动态链接库 M
  • 记录开发中使用的设计模式之发布订阅者模式(观察者模式)

    一 开发场景 当我们在开发中涉及到大量的调用跨应用API的时候 需要按照场景书写大量的重复性代码 常规的做法就是通过if else进行场景判断 进行调用 代码十分的冗余 重复性的调用方法 不利于后期的维护 而为了更好的针对某些场景 去调用对