一个关于规则处理的代码设计问题请教

发布于 2022-09-04 09:00:58 字数 1252 浏览 11 评论 0

业务介绍

商品可以打上特定的标签 如9.9元秒杀 特价款 5折抢购 标签有限制用券规则 如

  • 禁止用券

  • 禁止使用XX元以上的优惠券

  • 禁止使用店铺券

于是当下单展示可用优惠券列表时 需要基于商品的标签 排除相应的券

为了解耦 调用标签模块的接口 得到禁止用券的规则 如

    Map<String,String> getDisableCouponRule(int tagId);

返回结果有

  • disableAll : true (禁止用券)

  • disableCouponPriceGreatEqual : 30 (禁止使用30元以上(含)的优惠券)

  • disableCouponType : shop (禁止使用店铺券)

然后基于返回的规则 排除相应的优惠券 如


if("true".equals(ruleMap.get("disableAll"))){
    return empty_list;   
}
for (Coupon coupon : couponList){ // 遍历用户优惠券 排除不符合条件的优惠券
    if(ruleMap.get("disableCouponPriceGreatEqual") != null){
        if(coupon.getPrice() >= parseInt(ruleMap.get("disableCouponPriceGreatEqual"))){
            continue;
        }
    }
    if(ruleMap.get("disableCouponType")!=null){
        if(coupon.getType() == getTypeIntValue(ruleMap.get("disableCouponType"))){continue;}
    }
}

目前业务还算简单 就这么几种规则 万一以后要新增规则 如

  • 小于YY元的优惠券不能使用

增加一个if语句就是了

但是总觉得if语句不够优雅 不知有没什么设计模式或DSL适合这种场景?

这种场景适合使用规则引擎吗? 是不是太重了?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

动听の歌 2022-09-11 09:00:58

最终决定采用spring el表达式来实现

  • 标签禁止用券 返回 "true"

  • 新人专享 (类目新客) 禁止使用40元以上的优惠券 couponPrice > 40

  • 特价款 5折抢购 禁止使用店铺优惠券 couponType == 2

代码示例

        String disabledCouponRule = "true"; // 禁止用券
        Coupon coupon = new Coupon(BigDecimal.valueOf(50),2); // 50元面额 店铺券
        ExpressionParser expressionParser = new SpelExpressionParser();
        Expression expression = expressionParser.parseExpression(disabledCouponRule);
        boolean result = expression.getValue(coupon, Boolean.class);
        assertTrue(result);
        
        String disabledCouponRule = "couponPrice > 40"; // 禁止使用40元以上的优惠券

        Coupon coupon = new Coupon(BigDecimal.valueOf(39),1);
        ExpressionParser expressionParser = new SpelExpressionParser();
        Expression expression = expressionParser.parseExpression(disabledCouponRule);
        boolean result = expression.getValue(coupon, Boolean.class);
        assertFalse(result); // 小于40 可用

        coupon = new Coupon(BigDecimal.valueOf(40),1);
        expression = expressionParser.parseExpression(disabledCouponRule);
        result = expression.getValue(coupon, Boolean.class);
        assertFalse(result); // 等于40 不可用

        coupon = new Coupon(BigDecimal.valueOf(41),1);
        expression = expressionParser.parseExpression(disabledCouponRule);
        result = expression.getValue(coupon, Boolean.class);
        assertTrue(result); // 大于40 不可用
        
        String disabledCouponRule = "couponType == 2"; // 禁止使用店铺优惠券 2表示店铺券

        Coupon coupon = new Coupon(BigDecimal.valueOf(30),1); // 平台券
        ExpressionParser expressionParser = new SpelExpressionParser();
        Expression expression = expressionParser.parseExpression(disabledCouponRule);
        boolean result = expression.getValue(coupon, Boolean.class);
        assertFalse(result); // 平台券 可用

        coupon = new Coupon(BigDecimal.valueOf(30),2);
        expression = expressionParser.parseExpression(disabledCouponRule);
        result = expression.getValue(coupon, Boolean.class);
        assertTrue(result); // 店铺券 不可用

参考文档
http://www.baeldung.com/sprin...

最美不过初阳 2022-09-11 09:00:58

如果真要这样
可以考虑

  • 责任链模式,把这个优惠券对象依次传递到每个过滤规则的过滤器当中,以后只需要增加不同规则的过滤器

如果我做这个的话,我会用广播的方式

  • 定义一个过滤器

  • 过滤器里面实现不同的过滤规则

  • 然后把这个优惠券数据赋值给过滤器

  • 再遍历一边过滤器里面不同的过滤算法

  • 后期只需要增加过滤器里面的过滤算法即可

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文