在代驾服务中,费用的计算往往涉及多个复杂的规则,比如不同时间段的起步价、里程费、等候费、远途费等。这些规则可能会随着业务变化而频繁调整,硬编码在业务逻辑中不仅维护成本高,而且不够灵活。Drools作为一款强大的规则引擎,可以帮助我们实现动态的业务规则管理。本文将通过Drools引擎,演示如何实现一个代驾计费系统。
一、主要规则模块
代驾计费规则通常包括以下几个方面:
- 起步价规则:不同时间段起步价不同,起步公里数也不同。
- 里程费规则:超出起步公里后的里程费计算。
- 等候费规则:根据等候时间的长短计算费用。
- 远途费规则:超过一定公里数后的远途附加费。
- 总费用计算:汇总所有费用得到订单总金额。
1. 起步价规则
起步价根据时间段而有所不同。具体规则如下:
- 00:00:00-06:59:59:起步价为19元,包含3公里。
- 07:00:00-23:59:59:起步价为19元,包含5公里。
global com.xxxxxx.daijia.model.vo.rules.FeeRuleResponse feeRuleResponse;
rule "起步价 00:00:00-07:00:00 19元(含3公里)"
salience 10
no-loop true
when
$rule: FeeRuleRequest(startTime >= "00:00:00" && startTime < "07:00:00")
then
feeRuleResponse.setBaseDistance(new BigDecimal("3.0"));
feeRuleResponse.setBaseDistanceFee(new BigDecimal("19.0"));
feeRuleResponse.setExceedDistancePrice(new BigDecimal("4.0"));
System.out.println("00:00:00-07:00:00 起步价:" + feeRuleResponse.getBaseDistanceFee() + "元,包含" + feeRuleResponse.getBaseDistance() + "公里");
end
rule "起步价 07:00:00-23:59:59 19元(含5公里)"
salience 10
no-loop true
when
$rule: FeeRuleRequest(startTime >= "07:00:00" && startTime <= "23:59:59")
then
feeRuleResponse.setBaseDistance(new BigDecimal("5.0"));
feeRuleResponse.setBaseDistanceFee(new BigDecimal("19.0"));
feeRuleResponse.setExceedDistancePrice(new BigDecimal("3.0"));
System.out.println("07:00:00-23:59:59 起步价:" + feeRuleResponse.getBaseDistanceFee() + "元,包含" + feeRuleResponse.getBaseDistance() + "公里");
end
2. 里程费规则
里程费计算的规则是:超出起步里程后,按公里数收费。不同时间段的里程费标准不同:
- 00:00:00-06:59:59:超出起步里程,每公里4元。
- 07:00:00-23:59:59:超出起步里程,每公里3元。
rule "里程费 00:00:00-06:59:59 4元/公里"
salience 10
no-loop true
when
$rule: FeeRuleRequest(startTime >= "00:00:00" && startTime <= "06:59:59" && distance > 3.0)
then
BigDecimal exceedDistance = $rule.getDistance().subtract(new BigDecimal("3.0"));
feeRuleResponse.setExceedDistance(exceedDistance);
System.out.println("里程费,超出里程:" + exceedDistance + "公里,单价: 4元/公里");
end
rule "里程费 07:00:00-23:59:59 3元/公里"
salience 10
no-loop true
when
$rule: FeeRuleRequest(startTime >= "07:00:00" && startTime <= "23:59:59" && distance > 5.0)
then
BigDecimal exceedDistance = $rule.getDistance().subtract(new BigDecimal("5.0"));
feeRuleResponse.setExceedDistance(exceedDistance);
System.out.println("里程费,超出里程:" + exceedDistance + "公里,单价: 3元/公里");
end
3. 等候费规则
当等候时间超过10分钟后,每分钟收取1元的等候费。如果等候时间在10分钟以内,则不收取费用。
rule "等候费 等候超过10分钟后 1元/分钟"
salience 10
no-loop true
when
$rule: FeeRuleRequest(waitMinute > 10)
then
Integer exceedWaitMinute = $rule.getWaitMinute() - 10;
feeRuleResponse.setExceedWaitMinute(exceedWaitMinute);
feeRuleResponse.setExceedWaitMinutePrice(new BigDecimal("1.0"));
System.out.println("等候费,超出分钟:" + exceedWaitMinute + "分钟,单价: 1元/分钟");
end
rule "无等候费"
salience 10
no-loop true
when
$rule: FeeRuleRequest(waitMinute <= 10)
then
System.out.println("等候费:无");
end
4. 远途费规则
当行程超过12公里后,每公里加收1元的远途费,否则不收取远途费。
rule "远途费 超过12公里后每公里1元"
salience 10
no-loop true
when
$rule: FeeRuleRequest(distance > 12.0)
then
BigDecimal exceedLongDistance = $rule.getDistance().subtract(new BigDecimal("12.0"));
feeRuleResponse.setExceedLongDistance(exceedLongDistance);
System.out.println("远途费,超出公里:" + exceedLongDistance + "公里,单价: 1元/公里");
end
rule "无远途费"
salience 10
no-loop true
when
$rule: FeeRuleRequest(distance <= 12.0)
then
System.out.println("远途费:无");
end
5. 计算总金额规则
最后,我们需要将所有的费用(起步价、里程费、等候费、远途费)累加,得到订单的总金额。
rule "计算总金额"
salience 10
no-loop true
when
$rule: FeeRuleRequest(distance > 0.0)
then
BigDecimal distanceFee = feeRuleResponse.getBaseDistanceFee().add(feeRuleResponse.getExceedDistance().multiply(feeRuleResponse.getExceedDistancePrice()));
BigDecimal waitFee = new BigDecimal(feeRuleResponse.getExceedWaitMinute()).multiply(feeRuleResponse.getExceedWaitMinutePrice());
BigDecimal longDistanceFee = feeRuleResponse.getExceedLongDistance().multiply(feeRuleResponse.getExceedLongDistancePrice());
BigDecimal totalAmount = distanceFee.add(waitFee).add(longDistanceFee);
feeRuleResponse.setTotalAmount(totalAmount);
System.out.println("总金额计算: " + totalAmount + "元");
end
6. 优化与扩展建议
-
规则灵活性:Drools的优势在于规则的灵活定义。随着业务规则的调整,开发人员无需修改代码逻辑,只需修改规则文件,系统即可实时适应新的业务需求。
-
规则维护:当规则变得复杂时,可以将规则文件模块化,按类别进行拆分,例如将里程费、等候费、远途费分成不同的规则文件,方便维护。
-
规则冲突:Drools支持规则优先级(
salience
),通过合理设置优先级可以有效避免规则冲突。 -
动态加载规则:Drools允许通过API动态加载规则文件,开发人员可以进一步扩展系统,做到规则的动态调整和热部署。
7. 总结
通过Drools,我们可以轻松实现代驾服务中的复杂计费规则。Drools让规则管理更加灵活和高效,当业务规则发生变化时,无需改动代码逻辑,只需调整规则文件。这在计费、优惠策略等需要灵活变动的场景下尤为实用。