Drools确实支持“全局变量”——称为全局变量——但你不能针对它们编写规则。他们通常不鼓励,但在过去,这就是您通常从规则集中返回值的方式。
List
这是一个将 a作为全局变量的简单示例:
global java.util.List result;
rule "All people whose name starts with 'M' will attend"
when
$person: Person( name str[startsWith] "M" )
then
result.add($person);
end
List<Person> attendees = new ArrayList<>();
KieSession session = this.getSession();
session.insert(person);
session.insert(person1);
session.insert(person2);
session.insert(person3);
session.insert(person4);
session.setGlobal("result", attendees);
session.fireAllRules();
// at this point, 'attendees' is populated with the result of the rules
但是,这对您不起作用,因为您无法在左侧(“何时”)与这些全局变量进行交互。
相反,您需要的是一个中间对象来处理您的中间计算。通常我会建议将这些值存储在对象本身上,但如果您有真正派生的数据,则没有合适的地方将其存储在您的模型中。
这是另一个简单的例子。在这里,我在一个 adhoc 对象中跟踪一些结果,因此我可以在后续规则中关闭它们。
declare Calculations {
intermediateValue1: int
intermediateValue2: double
}
rule "Create tracker object"
when
not(Calculations())
then
insert(new Calculations())
end
rule "Calculate some intermediate value 1"
when
$calc: Calculations()
// some other conditions
then
modify($calc) {
setIntermediateValue1( 42 )
}
end
rule "Calculate some other value using value 1 when > 20"
when
$calc: Calculations( $value1: intermediateValue1 > 20 )
// other conditions
then
modify( $calc ) {
setIntermediateValue2( $value1 * 3 )
}
end
rule "Final calculation"
when
$calc: Calculation( $value1: intermediateValue1 > 0,
$value2: intermediateValue2 > 0 )
// other conditions
then
// do the final calculation
end
该declare
关键字用于有效地定义 DRL 本身内的轻量级类。它不存在于 DRL 之外,也不能在 Java 中引用。因为我们只是在跟踪中间值,所以没关系。
第一条规则是查看我们的计算结果是否存在于工作记忆中。如果不是,它会插入一个。
inserts
关键字在这里很关键。它告诉 Drools 在它的工作内存中有新数据,它需要重新评估任何后续规则以确定它们现在是否可以触发。
中间两条规则与结果对象交互并修改值。请注意,我不只是调用设置器(例如$calc.setIntermediateValue1( 42 )
),而是使用modify
. 与 类似insert
,这让 Drools 知道工作内存中的这个特定对象已被修改,因此它重新评估依赖于该对象的任何规则并确定它现在是否可以执行。
最后一条规则采用所有中间计算值,并且(可能)对它们进行一些处理以找出“最终”计算值。
我的另一个答案谈到了insert
使数据更改对其他规则可见的不同操作(等)。