采用责任链+策略模式处理不同产品类型的佣金计算逻辑

设计了灵活的多级分销佣金计算规则引擎,支持20+种佣金计算规则
在分销场景中,佣金计算是个复杂的业务,主要涉及多级渠道分佣、团队分佣、个人分佣等场景。我们设计了一个灵活的佣金计算引擎来处理这些复杂的规则。

1.传统方式实现(不使用规则引擎):

public class TraditionalCommissionService {  
    public BigDecimal calculateCommission(Order order) {  
        // 基础佣金  
        BigDecimal commission = BigDecimal.ZERO;  

        // 计算基础佣金  
        if (order.getProductType().equals("枚举:一类分销员")) {  
            commission = order.getAmount().multiply(new BigDecimal("0.1"));  
        } else if (order.getProductType().equals("枚举:二类分销员")) {  
            commission = order.getAmount().multiply(new BigDecimal("0.15"));  
        }  

        // 计算团队奖励  
        if (order.getTeamPerformance().compareTo(new BigDecimal("1000000")) > 0) {  
            commission = commission.add(order.getAmount().multiply(new BigDecimal("0.01")));  
        }  

        // 计算渠道奖励  
        if (order.getChannelLevel().equals("A")) {  
            commission = commission.add(order.getAmount().multiply(new BigDecimal("0.02")));  
        } else if (order.getChannelLevel().equals("B")) {  
            commission = commission.add(order.getAmount().multiply(new BigDecimal("0.015")));  
        }  

        // 更多的if-else...  
        return commission;  
    }  
}

这种传统方式的问题:

  • 代码臃肿:随着规则增加,if-else嵌套越来越多
  • 难维护:修改一个规则可能需要改动多处代码
  • 不灵活:规则修改需要改代码重新发布
  • 难扩展:新增规则需要修改原有代码
  • 业务耦合:业务规则和代码逻辑混在一起

2.使用规则引擎的方式:

// 1. 领域模型定义  
public class TeamPerformanceBonusRule implements CommissionRule {  
    private static final BigDecimal PERFORMANCE_THRESHOLD = new BigDecimal("1000000");  
    private static final BigDecimal BONUS_RATE = new BigDecimal("0.01");  
    
    @Override  
    public BigDecimal calculate(Order order) {  
        Agent agent = order.getAgent();  
        
        if (agent.getMonthlyPerformance().compareTo(PERFORMANCE_THRESHOLD) > 0) {  
            return order.getAmount().multiply(BONUS_RATE);  
        }  
        return BigDecimal.ZERO;  
    }  
    
    @Override  
    public String getRuleName() {  
        return "团队业绩奖励规则";  
    }  
}  

// 3.4 渠道奖励规则  
public class ChannelBonusRule implements CommissionRule {…}  

// 3.5 新人奖励规则  
public class NewAgentBonusRule implements CommissionRule {…}  

// 4. 佣金计算结果  
public class CommissionResult {…}  

// 5. 规则链处理器  
@Slf4j  
public class CommissionRuleChain {  
    private final List<CommissionRule> rules = new ArrayList<>();  
    
    public CommissionRuleChain() {  
        // 按照处理顺序添加规则  
        rules.add(new BaseCommissionRule());  
        rules.add(new AgentLevelBonusRule());  
        rules.add(new TeamPerformanceBonusRule());  
        rules.add(new ChannelBonusRule());  
        rules.add(new NewAgentBonusRule());  
    }  
    
    public CommissionResult calculateCommission(Order order) {  
        CommissionResult result = new CommissionResult();  
        result.setOrderId(order.getOrderId());  
        result.setAgentId(order.getAgent().getAgentId());  
        result.setAgentName(order.getAgent().getName());  
        result.setOrderAmount(order.getAmount());  
        result.setCalculateTime(LocalDateTime.now());  
        
        for (CommissionRule rule : rules) {  
            try {  
                BigDecimal ruleCommission = rule.calculate(order);  
                result.addRuleResult(rule.getRuleName(), ruleCommission);  
                
                log.debug("规则[{}]计算结果: {}", rule.getRuleName(), ruleCommission);  
            } catch (Exception e) {  
                log.error("规则[{}]计算异常: {}", rule.getRuleName(), e.getMessage());  
            }  
        }  
        
        return result;  
    }  
}  

// 6. 佣金规则引擎服务  
public class CommissionRuleEngineService {  
    private final CommissionRuleChain ruleChain = new CommissionRuleChain();  
    
    public CommissionResult calculateCommission(Order order) {  
        log.info("开始计算订单[{}]的佣金,代理人:{}", order.getOrderId(), order.getAgent().getName());  
        CommissionResult result = ruleChain.calculateCommission(order);  
        log.info("订单[{}]佣金计算完成,总佣金:{}", order.getOrderId(), result.getTotalCommission());  
        return result;  
    }  
}

使用示例:

public class CommissionCalculationExample {
    public static void main(String[] args) {
        // 创建代理人  
        Agent agent = new Agent();
        agent.setAgentId("AG001");
        agent.setName("张三");
        agent.setLevel("专家");
        agent.setChannelLevel("A");
        agent.setTeamId("TEAM001");
        agent.setMonthlyPerformance(new BigDecimal("2000000"));
        agent.setJoinTime(LocalDateTime.now().minusDays(30));
        agent.setNewAgent(true);

        // 创建订单  
        Order order = new Order();
        order.setOrderId("ORD" + LocalDateTime.now().format(DateTimeFormatter.BASIC_ISO_DATE) + "001");
        order.setProductType("枚举:一类分销员");
        order.setAmount(new BigDecimal("100000"));
        order.setCreateTime(LocalDateTime.now());
        order.setAgent(agent);

        // 用规则引擎计算佣金
        CommissionRuleEngineService service = new CommissionRuleEngineService();
        CommissionResult result = service.calculateCommission(order);

        // 输出结果  
        System.out.println(result.toString());
    }
}

运行结果:
开始计算订单ORD20241220001的佣金,代理人:张三
规则基础佣金规则计算结果: 10000.0
规则代理人等级奖励规则计算结果: 5000.00
规则团队业绩奖励规则计算结果: 1000.00
规则渠道奖励规则计算结果: 2000.00
规则新人奖励规则计算结果: 2000.00
订单ORD20241220001佣金计算完成,总佣金:20000.00

佣金计算结果明细:
订单号:ORD20241220001
代理人:张三(AG001)
订单金额:¥100000
规则计算明细:
- 基础佣金规则: ¥10000.0
- 代理人等级奖励规则: ¥5000.00
- 团队业绩奖励规则: ¥1000.00
- 渠道奖励规则: ¥2000.00
- 新人奖励规则: ¥2000.00
总佣金:¥20000.00

这个实现的优点:

  1. 代码结构清晰,每个规则独立封装
  2. 易于添加新规则,不需要修改现有代码
  3. 规则的执行顺序可控
  4. 便于单元测试
  5. 规则配置可以轻松扩展为从配置文件或数据库加载

总的来说,规则引擎特别适合分销这种业务规则复杂、经常变动的场景。它通过将业务规则从代码中抽离出来,实现了规则的灵活配置和管理,大大提高了系统的可维护性和扩展性。