基于Java的简单规则引擎带有备用方案

huangapple go评论99阅读模式
英文:

Java based simple rule engine with fallback

问题

我需要实现一个带有分层回退支持的简单规则引擎。我已经研究过DROOLS库,但我不确定它是否支持我的用例。

用例相当简单,这让我在思考是否需要规则引擎?尽管如此,以下是用例 -

我有一个带有一堆字段的模型

  1. Public Class Entity {
  2. public int val0;
  3. public int val1;
  4. public int val2;
  5. public int val3;
  6. .....
  7. }

现在,我想针对这些字段创建以下规则

  1. RULE1 --- IF val0 == 1 && val1 == 1 && val2 == 1 && val3 == 1 --- (1,1,1,1) THEN DO this
  2. RULE2 --- IF val0 == 1 && val1 == 1 && val2 == 1 && val3 == 2, --- (1,1,1,2) THEN DO this
  3. RULE3 --- IF val0 == 1 && val1 == 1 && val2 == 1 && val3 == *, --- (1,1,1,*) THEN DO this
  4. RULE4 --- IF val0 == 1 && val1 == 1 && val2 == * && val3 == *, --- (1,1,*,*) THEN DO this

问题出现在RULE3RULE4,其中val2和val3可以匹配任何值。

例如

  1. val0=1val1=1val2=1val3=1 -- 应执行RULE1 - 具体匹配
  2. val0=1val1=1val2=1val3=3 -- 应执行RULE3 - 由于val3没有特定的匹配因此为通用匹配
  3. val0=1val1=1val2=10val3=5 -- 应执行RULE4 - 由于val2val3没有特定的匹配因此为通用匹配

因此,根据查询,我要么会找到匹配的规则,要么必须回退到更通用的规则。是否存在现有的规则引擎库提供此功能,或者是否我甚至需要规则引擎库来实现此功能?

英文:

I need to implement a simple rules engine with hierarchical fallback support. I have already looked into the DROOLS library but I am not sure if it supports my use case.

The use case is rather simple which makes me thinking whether I need a rules engine at all? Nevertheless, here is the use case -

I have a modal with bunch of fields

  1. Public Class Entity {
  2. public int val0;
  3. public int val1;
  4. public int val2;
  5. public int val3;
  6. .....
  7. }

Now, I want to create rules against these fields as follow

  1. RULE1 --- IF val0 == 1 && val1 == 1 && val2 == 1 && val3 == 1 --- (1,1,1,1) THEN DO this
  2. RULE2 --- IF val0 == 1 && val1 == 1 && val2 == 1 && val3 == 2, --- (1,1,1,2) THEN DO this
  3. RULE3 --- IF val0 == 1 && val1 == 1 && val2 == 1 && val3 == *, --- (1,1,1,*) THEN DO this
  4. RULE4 --- IF val0 == 1 && val1 == 1 && val2 == * && val3 == *, --- (1,1,*,*) THEN DO this

The problem is with RULE3 and RULE4 where val2 and val3 can match any value.

e.g.

  1. val0=1, val1=1, val2=1, val3=1 -- should execute RULE1 - specific match
  2. val0=1, val1=1, val2=1, val3=3 -- should execute RULE3 - generic match as there's no specific match for val3
  3. val0=1, val1=1, val2=10, val3=5 -- should execute RULE4 - generic match as there's no specific match for val2 and val3

So depending on the query, either I will find the matching rule or I will have to fallback to the more generic rules. Is there any existing rules engine library that provides this functionality or rather do I even need a rules engine library to implement this functionality?

答案1

得分: 2

起初我认为你可能想考虑使用位逻辑,但由于某些字段采用非二进制值,这对你可能没有实际作用。

然而,解决方案不必太复杂。只需创建一个类,作为Entity值的匹配器,并使用一系列的if-else语句来寻找匹配项。

  1. class EntityMatcher {
  2. private Integer val0, val1, val2, val3;
  3. /** 用于匹配所有参数的构造函数 */
  4. EntityMatcher(int val0, int val1, int val2, int val3) {
  5. // 设置字段 0-3
  6. }
  7. /** 当不关心 val2 和 val3 时使用的构造函数 */
  8. EntityMatcher(int val0, int val1) {
  9. // 设置字段 0 和 1,将 val2 和 val3 设置为 null
  10. }
  11. boolean matches(Entity toMatchAgainst) {
  12. return (this.val0 == null || this.val0 == toMatchAgainst.val0)
  13. && (this.val1 == null || this.val1 == toMatchAgainst.val1)
  14. ...
  15. && (this.valN == null || this.valN == toMatchAgainst.valN);
  16. }
  17. }

然后你的规则引擎可能看起来像这样:

  1. if (new EntityMatcher(1, 1, 1, 1).matches(entity))
  2. // 规则 1
  3. else if (new EntityMatcher(1, 1, 1, 2).matches(entity))
  4. // 规则 2
  5. ...
  6. else if (new EntityMatcher(1, 1).matches(entity))
  7. // 规则 4
  8. ...
  9. else
  10. // 没有匹配项

这本质上与Scala中的case类相同。

英文:

At first I thought you might want to consider using bitwise logic, but with some of the fields taking non-binary values this probably doesn't really work for you.

However, the solution needn't be that complicated. Just create a class that acts as a matcher for the values of Entity and use a chain of if-else statements to find the match.

  1. class EntityMatcher {
  2. private Integer val0, val1, val2, val3;
  3. /** Constructor used to match all the parameters */
  4. EntityMatcher(int val0, int val1, int val2, int val3) {
  5. // set fields 0-3
  6. }
  7. /** Constructor used when you don't care about val2 & val3 */
  8. EntityMatcher(int val0, int val1) {
  9. // set fields 0 & 1, leaving val2 and val3 as null
  10. }
  11. boolean matches(Entity toMatchAgainst) {
  12. return (this.val0 == null || this.val0 == toMatchAgainst.val0)
  13. && (this.val1 == null || this.val1 == toMatchAgainst.val1)
  14. ...
  15. && (this.valN == null || this.valN == toMatchAgainst.valN);
  16. }
  17. }

Then your rules engine could look something like this:

  1. if (new EntityMatcher(1, 1, 1, 1).matches(entity))
  2. // Rule 1
  3. else if (new EntityMatcher(1, 1, 1, 2).matches(entity))
  4. // Rule 2
  5. ...
  6. else if (new EntityMatcher(1, 1).matches(entity))
  7. // Rule 4
  8. ...
  9. else
  10. // no match

This is essentially the same idea as case classes in Scala.

huangapple
  • 本文由 发表于 2020年9月22日 05:26:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/64000201.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定