drools7 rule的优化写法,规则继承或扩展

本文将介绍drools7中规则的继承。官方文档对应章节标题为 “conditional named consequences”,这里之所以称之为“继承”是因为在编写rule时会用到“extends ”,这样翻译其实是有一定问题的,翻译为扩展更准确些。本文将结合官方文档中的案例进行阐述。

       通常每个rule只会写一个then,当多个rule仅其中某一个条件不一致时,就会写很多重复的代码,举个例子:假设某购物中心为吸引客户,决定给60岁以上的客户提供10%的优惠,并且给予免费停车的权益。

entity:

//客户
public class Customer {
    private Integer id;
    private int age;
    private String level;
    private double discount;
    
}
//客户的车辆
public class Car {
    private Integer id;
    private Integer owner;//车主id,即customer的id
    private boolean freeParking;
}

kiesession初始化和插入数据源:

KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer =kieServices.getKieClasspathContainer();
KieBase kiebase = kieContainer.getKieBase();
KieSession kieSession = kieContainer.newKieSession();

Customer customer = new Customer(1,61,0.0,"golden");
Car car =new Car(1,customer.getId(),false);
kieSession.insert(customer);
kieSession.insert(car);
kieSession.fireAllRules();
kieSession.dispose();

1. 规则传统写法:

//方案1
rule "Give 10% discount to customers older than 60_f"
    when
        $c:Customer(age > 60)
    then
        System.out.println("方案1:Give 10% discount!");
end

rule "Give free parking to customers older than 60_f"
when
    $c:Customer(age > 60)
    Car(owner == $c.id)
then
    System.out.println("方案1:Free parking!");
end

执行结果:

方案1:Give 10% discount!
方案1:Free parking!

分析:好的,没问题,但是 $c:Customer(age > 60)这一句每个rule里都需要写一遍,所以代码重复、维护起来较麻烦。

2. 再看,使用extends的写法:

//方案2
rule "Give 10% discount to customers older than 60_s"
    when
        $c:Customer(age > 60)
    then
    System.out.println("方案2:Give 10% discount!");
end

rule "Give free parking to customers older than 60_s"
    extends "Give 10% discount to customers older than 60_s"
when
    Car(owner == $c.id)
then
    System.out.println("方案2:Free parking!");
end

执行结果:

方案2:Give 10% discount!
方案2:Free parking!

分析:好的,也没问题,第二个rule使用extends基于第一个rule扩展了规则条目并配置了更多的数据处理方式,第二个规则依赖于第一规则中的规则条目,第一个规则改动conditions时第二个规则也会同时生效,维护难度的问题得到解决,但是写法上似乎还是比较繁琐。

3. 继续优化写法:

//方案3
rule "Give 10% discount and free parking to customers older than 60_f"
    when
        $c:Customer(age > 60)
        do[giveDiscount]
        Car(owner == $c.id)
    then
        System.out.println("方案3:Free parking!");
    then[giveDiscount]
        System.out.println("方案3:Give 10% discount!");
end

执行结果:

方案3:Give 10% discount!
方案3:Free parking!

分析:写法相当清秀,上述规则包含两个条件,触发了默认规则处理(第一个then),另外通过do关键字又触了“giveDiscount”规则处理代码,do的作用是当do之前的规则条目都匹配的时候就会触发do后边中括号里绑定的标签所对应的的then。其本质就是将方案1中的两个规则合并为一个规则写,运行过程可以按方案1解释。

4. 拓展案例

      写这篇文章的初衷其实是因为在技术群中看到有人问到一个问题,当规则条件中存在或的关系时,想知道具体是因为符合了哪个条件,那这里其实可以理解为对于符合规则的数据除了共有的处理以外,还有各自独特的输出,即规则规定数据符合条件A或条件B时,均输出成功信息,同时符合A条件的另外输出A,符合B条件的另外外输出B。通常的写法是拆分为两个rule去写,但是额外的输出又不是那么重要,拆分的话开发成本就会增加。这时候用对案例3进行一下升级改造就可以完美解决。

     假设上述的购物中心对活动决策做了进一步调整,针对60岁以上的客户,“golden”级别的给予20%的优惠,“level”级别的给予10%的优惠,其他级别的优惠5%;给予免费停车的权益。

规则如下:

//方案4
rule "Give 10% discount and free parking to customers older than 60_s"
    when

        $c:Customer(age > 60,$l:level)
        if ($l == "golden") do[golden]
        else if ($l == 'silver') do[silver]
        else do[other]
        Car(owner == $c.id)
    then
        System.out.println("方案4:Free parking!");
    then[golden]
        System.out.println("方案4:golden, Give 20% discount!");
    then[silver]
        System.out.println("方案4:silver, Give 10% discount!");
    then[other]
        System.out.println("方案4:other, Give 5% discount!");
end

运行结果:

方案4:golden, Give 20% discount!
方案4:Free parking!

分析:这里又有了if/else的嵌套if、else if、else之间属于互斥关系,当if之前的条件匹配并且if中的条件时,就会触发其后do所绑定标签所对应的的then。

      另外处理do关键字,还有break关键字,当触发break所绑定的标签时,其后的所有条件均不会在进行匹配,此时也不会再触发默认then了(即第一个then),示例如下:

rule "Give 10% discount and free parking to customers older than 60_s"
    when

        $c:Customer(age > 60,$l:level)
        if ($l == "golden") break[golden] //触发break绑定的标签[golden]所对应的的then
        else if ($l == 'silver') do[silver]
        else do[other]
        Car(owner == $c.id)//因为break被触发,这里不会执行条件匹配
    then
        System.out.println("方案4:Free parking!");//因为break,这里也不会被执行
    then[golden]
        System.out.println("方案4:golden, Give 20% discount!");//触发
    then[silver]
        System.out.println("方案4:silver, Give 10% discount!");
    then[other]
        System.out.println("方案4:other, Give 5% discount!");
end

执行结果:

方案4:golden, Give 20% discount!

规则就是让我们带着锁链跳舞,要跳的好看,就要勤于思考,勇于尝试,好的想法会利用规则优雅的处理事情。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值