当前位置: 首页 > news >正文

基于模板设计模式开发优惠券推送功能以及对过期优惠卷进行定时清理

1.模板设计模式:

模板设计模式是一种常见的设计模式,主要作用是对 具体操作的 共有代码块进行提取,提升代码复用性。

那么说道代码复用性,首先想到的是抽象类而不是接口。

因为抽象类的本质就是为了代码复用,抽象类既可以包含抽象方法也可以包含具体方法。

在模板设计模式中,我们将 需要将原本共有的具体操作抽离并封装在抽象类的具体方法中。让抽象类的具体操作来实现需要被复用的逻辑。而其余的抽象方法是不同业务的 个性,各个业务可以按照自己的方式进行重写。这部分特性在模板设计模式中是为具体方法服务的。

2.开发优惠券推送功能

优惠券推送功能是根据excel导出方式来进行的。目前我们有一张优惠券,画像平台根据用户特性选取出符合这张优惠券的用户,从而导出一个excel表格,表格中装入的是符合发券特征的用户。我们的优惠券推送功能就是根据读取excel表格中的用户信息,将这张优惠券统一推送给目标用户。

对于优惠券发放,我们考虑到了定时发放和立即发放两种情况。由于定时发放使用传统的定时任务需要建立线程定时去扫描全表,造成数据库的较大开销,所以考虑使用RocketMQ来进行定时任务。

RocketMQ的延时消息任务,需要发送地址、消息以及发送时间三个参数。

public SendResult syncSendDelayTimeMills(String destination, Message<?> message, long delayTime) {return this.syncSend(destination, message, (long)this.producer.getSendMsgTimeout(), delayTime, DelayMode.DELAY_MILLISECONDS);
}

这是对应的rocketMQ的定时消息发送接口,需要destination,message,delayTime

2.1发送地址

对于不同的业务,建立不同的group,消费者会根据group从消息队列中接收自己想要的信息。

2.2消息

需要注意的是Message<?>是指上是Spring中的包import org.springframework.messaging.Message;

Message通过MessageBuilder进行构建,这部分内容就是消息实体。

2.3发送时间

delayTime就是指延迟发送的时间。

3.如何抽离出模板设计模式

由于我们的业务不仅有延时发送任务,还有立即发送任务,所以会为这两种任务设计消息发送类AbstractCommonSendProduceTemplate,很显然,这是共有的抽象类。

然后为不同的业务创建不同的实现类,继承AbstractCommonSendProduceTemplate。

3.1如何判断是立即发送还是延时发送?

我们只需要设计一个属性,根据属性的值来判断即可。这可以解决立即发送和延时发送的矛盾。在业务层无需再进行判断。

3.2具体如何完整实现模板设计模式?

在上面我们讲解了类的抽离,我们现在需要找立即发送与延时发送的区别,抽离出共性与特性。

共性很显然就是都需要使用rocketMQ进行消息发送。

1.特性:对于立即发送而言,需要的api不是syncSendDelayTimeMills而是syncSend,

public SendResult syncSend(String destination, Message<?> message, long timeout) {return this.syncSend(destination, message, timeout, 0);
}

timeout是超时时间。这是第一个特性。

2.处理的业务模块不同,在项目中,推送优惠券模块的推送功能可以是定时推送也可以是立即推送,包含这两种方式。

而对于优惠券创建模块的定时销毁过期优惠券功能目前只需要定时任务方式。

所以对于不同的业务,我们需要抽离出不同的事件,因为不同的业务需要的参数不同,这里我们的项目定义了两个事件类:CouponTaskExecuteEvent、CouponTemplateDelayEvent

基于上述的共性与特性,具体如何实现?

从顶层考虑,我们的目的是实现发送消息代码的复用,所以我们抽离代码的时候一般而言是先抽取主要逻辑,对应抽象类中的具体方法。

当具体方法因不同业务模块需要不同参数的时候我们再使用抽象方法对”个性“进行实现即可。也就是上述内容所说的抽象方法为具体方法服务的思想。

因为定时和立即发送api不同,所以我们需要一个dto类来传递一个属性来验证是定时发送还是立即发送。

所以现在我们需要创建一个共有的DTO类来辅助具体任务的开发。DTO应该包含多个业务的主要内容,所以对于这种模板设计模式而言,尽量使业务功能相近,不然在DTO设计时不好设计。

public class BaseSendExtendDTO {/*** 事件名称*/private String eventName;/*** 主题*/private String topic;/*** 标签*/private String tag;/*** 业务标识*/private String keys;/*** 发送消息超时时间*/private Long sentTimeout;/*** 具体延迟时间*/private Long delayTime;
}

事件名称用于分辨不同功能,主题用于不同消息类型的监听,如果是立即发送,则delayTime为null,用于判断信息类型。

需要注意的是,该DTO类只是用于辅助消息发送,和真正的业务无关。比如说用于判别目前的任务是那个业务模块,执行业务模块中的哪个任务,任务的信息发送是什么模式等等。

比如在:

public SendResult syncSendDelayTimeMills(String destination, Message<?> message, long delayTime) {

return this.syncSend(

destination, message,

(long)this.producer.getSendMsgTimeout(),

delayTime, DelayMode.DELAY_MILLISECONDS);

}

这个 发送api中,DTO类只控制destination与delayTime,而message是由事件决定的。

4.总结

通过上述DTO可以使得不同功能模块找到自己的实现方式(比如立即发送和延时发送就是通过判别DTO中delayTime是否为null,再比如通过Topic使得不同消费者只监听自己的内容)。

通过两个事件类对两个功能模块所需属性做了区分,实质上最终传递的内容就是对应的事件。

http://www.dtcms.com/a/270421.html

相关文章:

  • C++ 遍历可变参数的几种方法
  • 数据库表设计:图片存储与自定义数据类型的实战指南
  • C语言宏替换比较练习
  • 暑假算法日记第四天
  • 5.6.2、ZeroMQ源码分析
  • 利用AI Agent实现精准的数据分析
  • ARM环境openEuler2203sp4上部署19c单机问题-持续更新
  • VM上创建虚拟机以及安装RHEL9操作系统并ssh远程连接
  • 大模型系列——RAG-Anything:开启多模态 RAG 的新纪元,让文档“活”起来!
  • Proface触摸屏编程软件(GP-Pro EX)介绍及下载
  • 金融行业信息
  • 力扣-75.颜色分类
  • Sentinel入门篇【流量治理】
  • 行业实践案例:医疗行业数据治理的挑战与突破
  • 【RAG知识库实践】数据源Data Source
  • ABP VNext + .NET Minimal API:极简微服务快速开发
  • B. Shrinking Array/缩小数组
  • Web后端实战:(部门管理)
  • 数据结构*搜索树
  • 二极管常见种类及基本原理
  • 【牛客刷题】小红的red字符串
  • MyBatis-Plus:提升数据库操作效率的利器
  • AB实验的长期影响
  • 【数据结构】复杂度分析
  • SpringBoot框架完整学习指南
  • [创业之路-489]:企业经营层 - 营销 - 如何将缺点转化为特点、再将特点转化为卖点
  • 钉钉企业应用开发技巧:在单聊会话中实现互动卡片功能
  • 学习日记-spring-day43-7.8
  • 基于物联网架构的温室环境温湿度传感器节点设计
  • 扣子Coze纯前端部署多Agents