目录
- 回顾easy-rules的rules执行
- 如何想规则集合的构造
- 规则集合
- 定义普通规则集和执行
- 定义树形规则集
当弄清楚了一个规则的设计和执行逻辑后,接下来需要考虑的就是许多的规则如何组织了,即规则集的抽象设计。
来看一些例子
回顾easy-rules的rules执行
普通的规则集合
public class BasicRule implements Rule {
/**
* Rule name.
*/
protected String name;
/**
* Rule description.
*/
protected String description;
/**
* Rule priority.
*/
protected int priority;
@Override
public int compareTo(final Rule rule) {
if (getPriority() < rule.getPriority()) {
return -1;
} else if (getPriority() > rule.getPriority()) {
return 1;
} else {
return getName().compareTo(rule.getName());
}
}
使用TreeSet存储规则,具体是依靠规则的priority和name来排序存储到TreeSet中
public class Rules implements Iterable<Rule> {
private Set<Rule> rules = new TreeSet<>();
回到规则的执行逻辑org.jeasy.rules.core.DefaultRulesEngine#doFire
void doFire(Rules rules, Facts facts) {
if (rules.isEmpty()) {
LOGGER.warn("No rules registered! Nothing to apply");
return;
}
logEngineParameters();
log(rules);
log(facts);
LOGGER.debug("Rules evaluation started");
// 1。直接遍历执行
for (Rule rule : rules) {
final String name = rule.getName();
final int priority = rule.getPriority();
// 2。依据引擎参数和规则设定进行一些跳过处理
if (priority > parameters.getPriorityThreshold()) {
LOGGER.debug("Rule priority threshold ({}) exceeded at rule '{}' with priority={}, next rules will be skipped",
parameters.getPriorityThreshold(), name, priority);
break;
}
if (!shouldBeEvaluated(rule, facts)) {
LOGGER.debug("Rule '{}' has been skipped before being evaluated", name);
continue;
}
// 3。规则的执行
boolean evaluationResult = false;
try {
evaluationResult = rule.evaluate(facts);
} catch (RuntimeException exception) {
LOGGER.error("Rule '" + name + "' evaluated with error", exception);
triggerListenersOnEvaluationError(rule, facts, exception);
// give the option to either skip next rules on evaluation error or continue by considering the evaluation error as false
if (parameters.isSkipOnFirstNonTriggeredRule()) {
LOGGER.debug("Next rules will be skipped since parameter skipOnFirstNonTriggeredRule is set");
break;
}
}
// 4。如果规则执行命中
if (evaluationResult) {
LOGGER.debug("Rule '{}' triggered", name);
triggerListenersAfterEvaluate(rule, facts, true);
try {
triggerListenersBeforeExecute(rule, facts);
// 执行规则动作
rule.execute(facts);
LOGGER.debug("Rule '{}' performed successfully", name);
triggerListenersOnSuccess(rule, facts);
// 判断规则引擎是否设定了命中第一个规则后就跳过
if (parameters.isSkipOnFirstAppliedRule()) {
LOGGER.debug("Next rules will be skipped since parameter skipOnFirstAppliedRule is set");
break;
}
} catch (Exception exception) {
LOGGER.error("Rule '" + name + "' performed with error", exception);
triggerListenersOnFailure(rule, exception, facts);
if (parameters.isSkipOnFirstFailedRule()) {
LOGGER.debug("Next rules will be skipped since parameter skipOnFirstFailedRule is set");
break;
}
}
} else {
LOGGER.debug("Rule '{}' has been evaluated to false, it has not been executed", name);
triggerListenersAfterEvaluate(rule, facts, false);
if (parameters.isSkipOnFirstNonTriggeredRule()) {
LOGGER.debug("Next rules will be skipped since parameter skipOnFirstNonTriggeredRule is set");
break;
}
}
}
}
见注释:
- 按照优先级遍历执行,会判断是否有跳过规则
- 规则执行,如果命中,则执行规则下的动作,同时判断是否要结束此次规则引擎的执行
- 规则引擎可以设定是否执行了一个规则命中就跳出整个执行
这已经符合大部分的规则逻辑和实际情况了:符合所有条件或者只需要某个条件就够了。
如何想规则集合的构造
以普通人的经历来说基本可以有两种规则组织
第一种规则:
- 九年义务教育,高中,大学,硕士,博士…
按照正常的流程走,优先级必须是这样,每一关都得关关过,过不了就止步了。当然有例外了:
- 天资聪慧的可以进行跳级,即有些关可以不用闯了,跳过(可以看成规则的跳过逻辑)
- 在每一关过后,可能家庭、学校、社会有些小奖励(可以看成规则命中后的动作)
第二种规则:
当步入社会后,比较复杂起来了, 都是一个一个十字路口,掺杂着一些平行线
规则错综复杂,像一棵树,而第一种规则也适用于其中的某些阶段。可以看成规则命中后的动作
而在计算机的世界中表示上述两种规则集的组织结构显然是线性结构和树形结构。
规则集合
public interface RuleSet<T extends Rule> extends Identifiable<String>, Evaluable<RuleResult>, EvalTraceable {
/**
* 查找规则
*
* @param ruleId 规则id
* @return 规则
*/
T get(String ruleId);
/**
* 获取所有正式规则
*
* @return 规则集合
*/
Collection<T> getRules();
/**
* 对规则集进行求值
*
* @param context 引擎执行上下文
* @return 求值结果
*/
@Override
RuleResult eval(EngineExecutionContext context);
}
定义普通规则集和执行
List<Rule>
定义树形规则集
TreeSet<Rule>