事件机制原理剖析及实际业务应用说明

news2024/9/24 1:14:42

什么是事件?

一个特定的场景发生了一个特定的情况就是一个事件。

事件在设计中的作用

为对象之间解耦。
举例
现有用户中心和消息中心。
目前,有一个用户注册的场景,此场景要求用户注册成功后要给用户发送多渠道欢迎通知(微信、短信、邮件等)。
分析上述场景,用户注册由用户中心实现,通知由消息中心实现。场景的发起者由用户中心发起。
则形成一个流程
在这里插入图片描述肯定是先想到,在用户注册逻辑中调用消息中心提供的接口。业务流程上来说是正确的,但是这里产生了一个问题,用户中心和消息中心 产生了一个耦合点。
此场景耦合问题说明
1、当消息中心的消息接口发生变化时,需要通知用户中心改变其调用结构(明明是对方自己的接口调用发生了改变,却让我来跟着变化,不合理)
2、当不止消息中心有用户注册场景需求的时候,需要用户中心再加一次其它服务中心的业务调用。(不合理)

如何解耦

为解决上述问题,事件机制可以作为一个处理手段。我们让双方中心抽象出一层。
用户中心 - 抽象出 用户注册成功事件
消息中心 - 抽象出 用户注册成功监听
在这里插入图片描述
当用户完成注册时,用户中心只负责抛出用户注册成功事件。由其他多个中心监听用户注册成功事件是否发生。当发生后,各自从事件中获取到用户对象去执行自己的逻辑。
好处
1、不用管其它业务中心的接口使用方法如何(由他们自己处理)
2、当有更多的业务中心需要监听用户注册时,只需要在事件注册树上声明监听和事件的关系即可,对用户中心是无感的。用户中心只做一件事件:抛出用户注册成功事件就可以了。

以下为根据方案设计自己制作的一套模型

Event 分发器

<?php

namespace TanYong\Event\Core;

trait EventDispatch
{
    public static function dispatch(mixed ...$args) : void
    {
        $obj = (new \ReflectionClass(self::class))->newInstanceArgs($args);

        Event::trigger($obj);
    }
}

Event 注册树 及调度器

<?php
namespace TanYong\Event\Core;

/**
 * 事件调度中心
 *
 */
class Event
{
    /**
     * 事件注册树
     *
     * @var array
     */
    public static array $mapEvent = [];

    public static function listen(string $eventClass,array $closure) : void
    {
        if(isset(self::$mapEvent[$eventClass]))
        {
            array_push(self::$mapEvent[$eventClass],$closure);
        }else{
            self::$mapEvent[$eventClass] = [];
            self::listen($eventClass,$closure);
        }
    }

    public static function trigger(object $event) : void
    {
        $eventClass = (new \ReflectionObject($event))->getName();

        if(isset(self::$mapEvent[$eventClass]))
        {
            foreach(self::$mapEvent[$eventClass] as $listenerInfo)
            {
                $listener = (new \ReflectionClass($listenerInfo[0]))->newInstance();
                call_user_func([$listener,$listenerInfo[1]],$event);
            }
        }
    }
}

事件 - 对象 - 规范化

<?php

namespace TanYong\Event\Core;

interface EventInterface
{

}

测试

<?php
namespace TanYong\Event\TestEvent;
use TanYong\Event\Core\EventDispatch;
use TanYong\Event\Core\EventInterface;

class Event1 implements EventInterface
{
    use EventDispatch;

    public string $name;

    public int $age;

    public function __construct(string $name,int $age)
    {
        $this->name = $name;
        $this->age  = $age;
    }


}
<?php
namespace TanYong\Event\TestListener;

use TanYong\Event\Core\EventInterface;

class Listener1
{
    public function run(EventInterface $event)
    {
        var_dump((new \ReflectionObject($event))->getName());
    }
}
<?php

namespace TanYong\Event\TestListener;

use TanYong\Event\TestEvent\Event1;

class Listener2
{
    public function run(Event1 $event1)
    {
        echo $event1->name;
    }
}

index.php

<?php
require "vendor/autoload.php";

//注册事件
\TanYong\Event\Core\Event::listen(
    \TanYong\Event\TestEvent\Event1::class,
    [\TanYong\Event\TestListener\Listener1::class,'run']
);
\TanYong\Event\Core\Event::listen(
    \TanYong\Event\TestEvent\Event1::class,
    [\TanYong\Event\TestListener\Listener2::class,'run']
);

//触发Event1事件
\TanYong\Event\TestEvent\Event1::dispatch("谭勇",27);

以上,为单机版解耦

以微服务为例,如何做业务解耦

依托rabbitmq 消息队列实现解耦或是依托red pub/sub 模型解耦
本质就是消息分发,发布和监听的操作。

redis - pub/sub 模型
在这里插入图片描述
用户注册成功后,由用户中心发布消息至redis,此时监听着用户注册消息的消息中心和其它中心一旦捕获到用户注册成功的事件消息发生,就各自执行自己的业务。

RabbitMQ 消息队列
在这里插入图片描述
当用户注册发生后,会触发事件的生成,事件本身会向RabbitMQ队列推送需要告知的服务中心由哪些。达到解耦目的。

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

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

相关文章

(11) XGBoost

文章目录 1 简要介绍2 梯度提升树2.1 提升集成算法&#xff1a;重要参数n_estimators2.2 有放回随机抽样&#xff1a;重要参数subsample2.3 迭代决策树&#xff1a;重要参数 η \eta η 3 XGBoost的智慧3.1 选择弱评估器&#xff1a;重要参数booster3.2 目标函数&#xff1a;重…

SpringCloud_微服务基础day2(Eureka注册中心:服务注册与发现

p6:Eureka简介与依赖导入 前面我们了解了如何对单体应用进行拆分&#xff0c;并且也学习了如何进行服务之间的相互调用&#xff0c;但是存在一个问题&#xff0c;就是虽然服务拆分完成&#xff0c;但是没有一个比较合理的管理机制&#xff0c;如果单纯只是这样编写&#xff0c…

HBase:(三)HBase API

HBase:(一)安装部署_只爱大锅饭的博客-CSDN博客hbase部署安装https://blog.csdn.net/qq_35370485/article/details/130988364?spm1001.2014.3001.5501 1.创建maven项目 2.添加依赖 <dependency><groupId>org.apache.hbase</groupId><artifactId>hba…

【鲁棒】对信息不完整的 DSGE 模型进行鲁棒预测(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

使用 TiUP 部署 TiDB 7.1.0 集群

使用 TiUP 部署 TiDB 7.1.0 集群 参考官方文档 1. 下载社区版安装包 TiDB 社区版 TiDB 7.1.0 为长期支持版本 (Long-Term Support Releases, LTS)。 TiDB-community-server 软件包 TiDB-community-toolkit 软件包 wget https://download.pingcap.org/tidb-community-ser…

【论文阅读】Attention-based Deep Multiple Instance Learning

misc{Ilse_Tomczak_Welling_2018, title{Attention-based Deep Multiple Instance Learning}, journal{International Conference on Machine Learning}, author{Ilse, Maximilian and Tomczak, JakubM. and Welling, Max}, year{2018}, month{Jul} }1、摘要与引言 本文…

CodeForces..走路的男孩.[简单].[时间间隔]

题目描述&#xff1a; 题目解读&#xff1a; 数学上的遛狗问题。 大意就是需要遛狗&#xff0c;一天至少两次&#xff0c;每次至少120分钟&#xff0c;题中所给的时间轴是从0-1440分钟&#xff0c;表示一整天。 然后它的主人正在不断接收信息&#xff08;在工作&#xff09;…

作用域 (局部作用域和全局作用域) 详细介绍

作用域 (局部作用域和全局作用域) 详细介绍 作用域是当前的执行上下文&#xff0c;值和表达式在其中“可见”或可被访问。 常见的作用域为&#xff1a; 全局作用域&#xff1a;脚本模式运行所有代码的默认作用域 函数作用域&#xff1a;由函数创建的作用域 局部作用域&#xff…

附录1-小程序常用标签

目录 1 view 2 scroll-view 3 swiper与swiper-item 4 text 5 rich-text 6 button 7 image 1 view 相当于html的div 2 scroll-view scroll-view是一个有滚动条的div scroll-y是允许纵向滚动&#xff0c;scroll-x是允许横向滚动 3 swiper与swiper-item swipe…

文盘Rust -- tokio绑定cpu实践 | 京东云技术团队

tokio 是 rust 生态中流行的异步运行时框架。在实际生产中我们如果希望 tokio 应用程序与特定的 cpu core 绑定该怎么处理呢&#xff1f;这次我们来聊聊这个话题。 首先我们先写一段简单的多任务程序。 use tokio::runtime; pub fn main() {let rt runtime::Builder::new_mu…

华为OD机试真题 Java 实现【通信误码】【2022Q4 100分】,附详细解题思路

一、题目描述 信号传播过程中会出现一些误码&#xff0c;不同的数字表示不同的误码ID&#xff0c;取值范围为1~65535&#xff0c;用一个数组记录误码出现的情况。 每个误码出现的次数代表误码频度&#xff0c;请找出记录中包含频度最高误码的最小子数组长度。 二、输入描述 …

Nginx+花生壳实现个人网站

下载Nginx Windows版本&#xff0c;目前稳定版1.24&#xff0c;Mainline的版本是1.25 Nginx下载后是一个zip文件&#xff0c;选择适当的位置解压。 首先修改一下Nginx的配置文件nginx.conf&#xff0c;位于conf目录下面&#xff1a; 配置文件我只修改了访问的端口号&#xff…

文件操作之文件包含全解(31)

文件包含的作用就是将这个文件包含进去之后&#xff0c;会调用指定文件的代码。先将文件包含才能执行里面的一些相关代码&#xff0c;比如所想进行文件的链接&#xff0c;数据库的查询&#xff0c;就可以先包含一个数据库的配置文件&#xff0c; 再去链接的话就享有配置文件的一…

2023年6月北京/广州/深圳CDGA/CDGP数据治理认证招生

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

C#发送邮箱设置及源码

用C#调用发送邮箱代码之前需要邮箱开通SMTP/POP3及设置授权码&#xff0c;开通及获取方法如下&#xff1a; 1、打开邮箱&#xff0c;登录邮箱&#xff0c;进入设置&#xff0d;》帐户 2、在“帐户”设置中&#xff0c;找到服务设置项&#xff0c;进行设置&#xff0c;如下…

什么是软件测试?这份工作到底怎么样?

什么是软件测试&#xff1f;这份工作到底怎么样&#xff1f; 着人工智能时代的到来&#xff0c;IT行业受到了越来越多人的重视。软件测试作为把控软件质量必不可少的环节&#xff0c;其重要性可见一斑。 那么从事软件测试行业究竟有前途吗?今天我们就来详细的介绍一下软件测…

第34步 机器学习实战DLC:不平衡数据处理(上)

失踪人口回归的第一期&#xff0c;来说一说不平衡数据。 一、不平衡数据的概念 什么是不平衡数据&#xff1f;我们先来看看小Chat怎么说的&#xff1a; 顾名思义&#xff0c;就是你的因变量1和0的样本数差距有点大&#xff0c;大到影响了模型性能。举个栗子&#xff0c;一个盒…

详解CenterFusion损失函数初始化及前向传播过程

CenterFusion损失函数Loss初始化_get_losses函数以及计算过程forward函数 1. 损失函数初始化前序运行逻辑2. 损失函数初始化2.1 loss函数初始化——Trainer类中的_get_losses()函数2.2 model_with_loss的初始化 3. loss计算过程前序运行逻辑4. loss计算过程4.1 loss计算函数调用…

chatgpt赋能python:Python圆柱体积计算器:简单、高效、快速解决计算难题

Python圆柱体积计算器&#xff1a;简单、高效、快速解决计算难题 圆柱体积是一个在日常生活、工程学、数学等领域都十分普遍的概念&#xff0c;可以用来计算许多实际问题中的体积&#xff0c;比如容器的容量、建筑材料的用量等等。在本文中&#xff0c;我们将介绍如何使用Pyth…

部署和配置DHCP服务器实验:自动分配IP地址和网络配置

部署和配置DHCP服务器实验&#xff1a;自动分配IP地址和网络配置 【实验目的】 部署DHCP服务器。熟悉DHCP服务器的配置方法。验证拓扑。 【实验拓扑】 实验拓扑如图所示。 设备参数如下表所示。 设备 接口 IP地址 子网掩码 默认网关 DHCPSERVE F0/0 172.16.10.1 25…