我想是的,但我不太确定。例如:
class Person {
int age;
int salary;
int bonus;
//getter and setter
public int calcIncome () {
return salary + bonus;
}
}
Run Code Online (Sandbox Code Playgroud)
博士升:
when
$p:Person(age > 30, calcIncome() > 1000)
then
...
Run Code Online (Sandbox Code Playgroud)
它是否等于:
if (person.getAge() > 30 && person.calcIncome() > 1000) {
...
}
Run Code Online (Sandbox Code Playgroud)
那么当人的年龄不大于30岁时,calcIncome方法将不会被评估?
谢谢!
我自己做了一些测试,这就是我发现的(至少在 6.3 版本中)。
Drools 中特定规则的 RETE 算法的 alpha 子网络始终按顺序进行评估。节点的顺序似乎是约束在它们所属的模式中的顺序。因此,我们可以说存在隐含的短路机制。
顺便说一句,我没有发现逗号“,”或与号“&&”的使用之间有任何区别。在这两种情况下,Drools 将表达式视为 2 个独立的 alpha 节点。
这就是我所做的:
public class Person {
private int age;
private int salary;
private int bonus;
public Person(int age, int salary, int bonus) {
//set values
}
public int calcIncome() {
throw new IllegalStateException("Expected error here!");
}
//getters
}
Run Code Online (Sandbox Code Playgroud)
请注意我是如何故意抛出异常的calcIncome().
该规则使用 '&&' 来指示 2 个约束之间的 AND 运算Person。同样,我通过使用逗号而不是与号得到了相同的结果。
rule "Rule A"
when
$p:Person(age > 30 && calcIncome() > 1000)
then
System.out.println("Rule A");
end
Run Code Online (Sandbox Code Playgroud)
先例规则的 Rete 网络如下所示:
在上图中,我们可以看到 2 个不同的 alpha 节点(黄色)。因为 alpha 节点是按顺序求值的,所以仅对第二个节点求值,在这种情况下,如果Person评估的时间超过 30 年。
使用超过 30 年和少于 30 年的实例进行的测试Person证实了这一点:超过 30 年的实例抛出了异常calcIncome()。
然后,我很好奇当我们使用 and 或 (||) 运算符而不是 and 时会发生什么。
rule "Rule B"
when
$p:Person(age > 30 || calcIncome() > 1000)
then
System.out.println("Rule B");
end
Run Code Online (Sandbox Code Playgroud)
有趣的是,此示例的 RETE 网络在单个 alpha 节点内解析 OR 运算符。
无论 Drools 内部使用什么机制(我猜是 MVEL)来解决这个节点,似乎都实现了逻辑短路。我所做的测试表明,仅当Person使用少于 30 年的实例时才会引发预期的异常。
即使 Drools 在处理单个模式内的约束时似乎会短路,但当规则包含多个模式时,情况就会有所不同。
根据我的测试,单个模式的所有约束都将使用短路启用算法来解决。这主要依赖于Rete网络中的alpha节点是按顺序评估的。
现在,当处理规则中的多个模式时,无法在编译时预测评估顺序。规则中的每个模式都可以根据特定 Rete 网络如何查找特定情况进行独立评估。
希望能帮助到你,
| 归档时间: |
|
| 查看次数: |
2082 次 |
| 最近记录: |