营销项目--5. 抽奖前置规则过滤
2024.7.12 day13
![[抽奖前规则过滤.png]]
情景
上一节完成了当用户抽奖的幸运值(消耗的积分)达到一定值时,分配可以抽奖的范围,需要从strategy实体中找到rule model字段,根据rule_weight在策略规则实体中找到对应的规则并进行解析,在装配策略时将规则装配到缓存中。
这一节需要实现抽奖前置权重和黑名单规则,
![[Pasted image 20240713095331.png]]模板模式,策略模式,工程模式本节使用了
任务
实现用户执行抽奖时判断是否已经超过N积分,如果超过N积分可以在限定范围内进行抽奖,同时如果用户是黑名单用户则只返回固定的奖品。实现涉及到工厂和策略定义出来的规则模型,并满足后续的规则扩展,
设计模式
策略模式
策略模式定义一系列算法,将每个算法封装起来,可以相互替换
抽奖规则过滤使用了策略模式,不同的策略(黑名单规则,权重规则)都是独立的过滤规则,每个规则都实现了ILogicFilter
接口,并且根据需要替换或更新规则
代码逻辑通过传入不同的ruleModel
选择不同的过滤器执行过滤规则。通过工厂类添加新策略
工厂模式
将对象的创建与使用分离,提供了一种创建对象的接口,具体的创建工作由工厂类负责DefaultLogicFactory
将所有规则逻辑RuleBlackListLogicFilter
RuleWeightLogicFilter
注册到logicFilterMap
中,使用时调用工厂,再选择合适的filter
进行规则过滤
模板方法模式
模板方法定义了算法的框架,允许子类重写某些步骤而不改变算法的结构AbstractRaffleStrategy
实现了模板方法模式,定义了抽奖的标准流程,将一些可变部分抽象为子类需要实现的钩子方法,比如规则过滤performRaffle
是模板方法,定义了抽奖的整体流程(参数校验,策略查询,规则过滤,抽奖结果)doCheckRaffleBeforeLogi
是抽象方法,由子类DefaultRaffleStrategy
实现,
新增4个实体类
RaffleAwardEntity
抽奖奖品实体。strategyId, awardId, awardKey, awardConfig, awardDesc
.awardKey和awardConfig
用于对接发奖策略,为了根据奖品的配置执行不同的发奖逻辑RaffleFactoryEntity
抽奖因子实体。userId, strategyId
. 封装了与用户参与抽奖相关的关键因子,主要用于在抽奖过程中传递用户信息以及所采用的抽奖策略,用来判断用户是否符合某些规则条件RuleActionEntity
规则动作实体 **泛型T
**:RuleActionEntity
使用泛型T
来支持不同阶段的规则实体(例如RaffleBeforeEntity
、RaffleCenterEntity
、RaffleAfterEntity
RuleMatterEntity
规则物料实体。userId, strategyId, awardId, ruleModel
, 封装了规则过滤时的必要信息,判断用户是否符合某些规则
行为
1. 在业务service层中创建一个执行抽奖接口
IRaffleStrategy: performRaffle(RaffleFactorEntity)
入参:抽奖因子实体(userID, strategyID)
返回: 抽奖奖品信息实体(strategyID, awardID, awardKey, awardConfig, awardDesc)
- 创建接口
- 创建抽奖因子和抽奖奖品实体类
- 在业务层servcie创建raffle package以及抽象抽奖策略类,用来定义抽奖的标准流程
2. 在service层创建规则package并定义一个抽奖规则逻辑过滤的接口
入参:规则物资(userID, strategyID, awardID, ruleModel)
返回: 规则动作ruleActionEntity
- 创建接口
- 创建规则物资和规则动作实体对象,注意的是在规则动作中使用泛型,分为抽奖前中后的三个规则动作
3. 定义一个DefalutLogicFactory工厂类和一个@LogicStrategy注解用来管理和实例化一组逻辑过滤器
逻辑过滤器由ILogicFilter
实现,根据不同的逻辑模式将它们存储在一个映射中,DefaultLogicFactory就可以用灵活的机制组织访问这些逻辑过滤器
- 管理逻辑过滤器实例: 接收所有逻辑过滤器的实现,并存储在一个线程安全的hashmap中
- 通过@LogicStrategy注解将每个逻辑过滤器与一个逻辑模式关联起来,根据逻辑模式存储在映射中
- 提供openLogicFilter方法用于返回存储的逻辑过滤器映射,使得业务逻辑可以根据需要访问和使用过滤器
4. implement过滤接口ILogicFilter
- 黑名单过滤接口 RuleBlackListLogicFilter
传入规则物料实体,返回规则行为实体 - 权重规则过滤接口
目前数据库中没有用户的积分值
后续是使用用户的积分值和策略规则中的权重进行比对,并按照权重规则来抽奖
5. 接口都开发好后,开发抽奖流程AbstractRaffleStrategy performRaffle
入参是抽奖因子实体(userId, strategyId)
返回抽奖奖品实体()
IRaffleStrategy
IRaffleStrategy
是抽奖策略接口,定义了一个performRaffle
方法,用于根据传入的RaffleFactorEntity
(包含用户和策略信息)执行抽奖,并返回抽奖奖品的结果。- 这个接口定义了抽奖系统的核心操作,后续不同的实现类可以根据具体的策略实现抽奖逻辑。
- 设计模式:这是标准的策略模式(Strategy Pattern)的应用,通过不同的实现类来定义不同的抽奖逻辑,确保抽奖逻辑可变且灵活。
ILogicFilter
ILogicFilter
是抽奖规则过滤接口,定义了规则过滤的行为。每个实现类会根据传入的RuleMatterEntity
进行规则校验,并返回RuleActionEntity
,其中封装了过滤结果。T
是一个泛型,表示不同阶段的规则实体,比如抽奖前的RaffleBeforeEntity
。- 设计模式:这是典型的策略模式(Strategy Pattern)的应用,通过不同的
ILogicFilter
实现类来定义不同的规则过滤逻辑,比如黑名单过滤和权重过滤。
DefaultLogicFactory
工厂模式,管理不同的逻辑过滤器ILogicFilter
实现类,根据不同业务需求返回相应的过滤器实例
1 | // 定义了一个线程安全的ConcurrentHashMap, 用来存储逻辑模式和响应的ILogicFilter实现(黑名单和权重值) |
@LogicStrategy
注解
通过@LogicStrategy
注解实现动态注册和解耦逻辑过滤器
**logicMode()
**:
- 注解的
logicMode()
定义了当前逻辑过滤器适用的规则模式,返回值是DefaultLogicFactory.LogicModel
枚举类型中的一个。每个LogicModel
代表一种规则类型,比如:RULE_WIGHT
:表示权重规则过滤。RULE_BLACKLIST
:表示黑名单规则过滤。
4. 流程总结:注解驱动+工厂模式
注册过滤器:
- 通过注解
@LogicStrategy
为每个过滤器标识其对应的规则类型。 - 工厂在启动时会扫描所有实现了
ILogicFilter
接口的类,并通过AnnotationUtils.findAnnotation()
识别类上的注解,将过滤器注册到logicFilterMap
中。
- 通过注解
调用过滤器:
- 当业务逻辑需要执行规则过滤时,工厂会从
logicFilterMap
中根据规则类型(rule_weight
或rule_blacklist
)提取相应的ILogicFilter
实现类,并调用其filter()
方法执行过滤逻辑。
- 当业务逻辑需要执行规则过滤时,工厂会从
扩展性:
- 如果未来增加新的规则过滤逻辑,比如
rule_vip
,只需定义新的ILogicFilter
实现类并使用@LogicStrategy(logicMode = DefaultLogicFactory.LogicModel.RULE_VIP)
注解即可,工厂会自动识别并注册,无需修改现有的工厂逻辑。
- 如果未来增加新的规则过滤逻辑,比如
AbstractRaffleStrategy
模板模式策略 实现IRaffleStrategy
接口,定义了抽奖的标准流程RaffleAwardEntity performRaffle(RaffleFactorEntity)
定义了抽奖的通用流程步骤,具体的抽奖前规则检查在DefaultRaffleStrategy
中的抽象方法doCheckRaffleBeforeLogic
实现
- 参数校验,根据入参拿到的抽奖因子实体
RaffleFactorEntity(userId, strategyId)
查看是否有空的现象 - 根据
strategyId
像仓储层查询策略实体strategyEntity(strategyId, strategyDesc, ruleModels)
, 主要是获取ruleModel
, 可能的结果是rule_weight, rule_blacklist
- 进行抽奖前规则过滤
doCheckRaffleBeforeLogic
进行规则过滤,根据规则过滤结果(返回一个RuleActionEntity
),判断是否需要接管 - 如果
TACK_OVER
:RULE_BLACKLIST
, 返回固定奖品id.RULE_WIGHT
根据权重信息返回进行抽奖 - 如果没有
TACK_OVER
, 进行默认抽奖流程
RuleBlackListLogicFilter
- 扫描到
LogicStrategy
注释,将filter放入hashmap中 - 从仓储层根据
strategyId, awardId, ruleModle
查询strategyRuleValue100:user001,user002,user003
- 将黑名单分组,比对userid是否在黑名单里,如果在,返回
TACK_OVER
的RuleActionEntity,如果不在返回放行的规则行为实体
RuleWeightLogicFilter
初始化:
- 类注解
@LogicStrategy
标识该类是权重规则过滤器,通过DefaultLogicFactory
动态加载到规则过滤机制中。 userScore
是用户当前积分,实际应用中通常会从数据库或服务中获取。
- 类注解
filter
方法:- 负责执行权重规则的过滤,接受一个
RuleMatterEntity
(规则物料实体)对象作为输入,包含用户 ID、策略 ID 等信息。 - 通过
repository.queryStrategyRuleValue()
从数据库查询规则值(例如,”4000:102,103,104”),表示在权重阈值4000
下可以抽取奖品102
、103
、104
。
- 负责执行权重规则的过滤,接受一个
解析权重规则:
getSplitWeightValue()
将规则字符串解析成Map<Long, String>
。例如,将 “4000:102,103 5000:105,106” 解析为:{4000: "4000:102,103", 5000: "5000:105,106"}
然后筛选出来比userScore小的最大的值就作为key
如果nextValue是存在的,就返回带有ruleWeightValueKey的RuleActionEntity