![[Pasted image 20241016140436.png]]
这一节主要是通过责任链设计模式重构之前的抽奖前过滤处理。因为在之前处理规则处理的流程中,因为前置规则的校验附带了抽奖的行为处理。让规则负责的事情变多了。

抽奖前置规则:黑名单抽奖策略,权重抽奖策略,白名单抽奖策略等。抽奖前置规则在抽奖中可以抽象为一种策略行为。这些策略行为之间应该为互斥的。所以想到了使用责任链设计模式

开发流程

  1. 将之前rule中的所有内容放在rule-filter中,新建rule-chain
  2. 增加责任链接口ILogicChain
  3. 增加一个抽象类AbstractLogicChain,封装链
  4. 实现具体的类,比如黑名单链BlackListLogicChain继承抽象类。以及兜底责任链,权重责任链的逻辑实现. 1. 黑名单根据用户id看数据库里这个id是否是黑名单用户,如果是,直接返回奖品。2. 权重规则,根据用户id查询用户已经消耗的积分值,按照数据库中的配置返回根据rule weight的抽奖结果。3.默认 进行标准抽奖
  5. 实现chain的工厂类
    可以调用工厂类的openLogicChain将对应strategyIdrule_model对应的过滤器装载进来
  6. 在AbstractRaffleStrategy中使用责任链 重构抽奖前的策略过滤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
重构之前:
//2. 策略查询
StrategyEntity strategy = repository.queryStrategyEntityByStrategyId(strategyId);

//3. 抽奖前的规则过滤
RuleActionEntity<RuleActionEntity.RaffleBeforeEntity> ruleActionEntity = this.doCheckRaffleBeforeLogic(RaffleFactorEntity.builder()
.userId(userId)
.strategyId(strategyId)
.build(), strategy.ruleModels());
if (RuleLogicCheckTypeVO.TAKE_OVER.getCode().equals(ruleActionEntity.getCode())){
if (DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode().equals(ruleActionEntity.getRuleModel())){
//黑名单返回固定奖品id
return RaffleAwardEntity.builder()
.awardId(ruleActionEntity.getData().getAwardId())
.build();
} else if (DefaultLogicFactory.LogicModel.RULE_WIGHT.getCode().equals(ruleActionEntity.getRuleModel())) {
//根据权重信息返回的进行抽奖
RuleActionEntity.RaffleBeforeEntity raffleBeforeEntity = ruleActionEntity.getData();
String ruleWeightValueKey = raffleBeforeEntity.getRuleWeightValueKey();
Integer awardId = strategyDispatch.getRandomAwardId(strategyId, ruleWeightValueKey);
return RaffleAwardEntity.builder()
.awardId(awardId)
.build();
}
}

//4. 默认抽奖流程
Integer awardId = strategyDispatch.getRandomAwardId(strategyId);

责任链模式中的核心思想:

  • 传递责任:如果当前责任链节点无法处理该请求,可以通过 next() 将责任传递给下一个责任链节点。
  • 灵活扩展:通过 appendNext 动态装配责任链节点,可以自由扩展链条的顺序和数量。

黑名单责任链

该责任链节点负责处理黑名单规则。它从仓储中查询到黑名单用户的规则值(包括奖品ID和黑名单用户列表)。如果当前用户在黑名单中,则直接返回固定奖品ID。

权重责任链

通过用户积分决定奖品的范围,并根据规则中的分组判断符合当前用户的奖品,如果用户的积分满足某个权重范围了,返回范围内的奖品Id

工厂类

logicChainGroup.get("default") 能够获取到对应的 ILogicChain 实现,主要是因为使用了 Spring 框架中的 @Component 注解,以及 Spring 容器 自动管理这些 Bean。
DefaultChainFactory 可以根据不同的策略规则配置,动态生成不同的责任链。这意味着当需要新增一种抽奖规则时,只需在 logicChainGroup 中添加一个新的责任链节点,然后在策略中配置相应的规则即可。

@Component 注解

@Component 注解: 在 Spring 框架中,@Component 是一个通用的注解,它告诉 Spring 框架需要将这个类作为一个 Bean 进行实例化并放入 Spring 容器中进行管理。
这些类通过 @Component("rule_blacklist")@Component("rule_weight") 注解注册到了 Spring 容器中,并且指定了 Bean 名称,如 "rule_blacklist""rule_weight"

  1. Spring 容器管理: 在 Spring 启动时,Spring 容器会自动扫描带有 @Component 的类,按照指定的名称(即注解中的名称)将这些类实例化为 Bean 并注册到容器中。于是,BackListLogicChain 类就注册为一个名为 "rule_blacklist" 的 Bean,RuleWeightLogicChain 类注册为一个名为 "rule_weight" 的 Bean
  2. 通过构造函数注入 logicChainGroup DefaultChainFactorylogicChainGroup 的注入依赖于 Spring 的 Map<String, ILogicChain> 自动装配功能。在 Spring 中,Spring 容器可以自动将所有实现了 ILogicChain 接口并标注了 @Component 的 Bean,按照 Bean 名称作为 Map 的键,Bean 本身作为 Map 的值,注入到 logicChainGroup 变量中。