规则引擎实现探讨

来源:百度文库 编辑:神马文学网 时间:2024/04/28 03:37:48
2007-01-10 21:58
最近在处理自定义表单时,需要自定义业务规则,最终在网上看到jxb8901先生的文章,和我的部分想法类似,特别是对于表达式的要求上,非常赞赏。区别在于我需要的表达式是基于组件的。原文如下:
一、问题
系统要求实现类似如下规则:
代码
积分规则:凭XX信用卡消费1元人民币,即可获得1分的消费积分,   在汽车类商户每消费100元人民币积8分,在房地产类商户每消费100元人民币积6分。   兑奖规则:100分~300分:兑换150元礼品,300分~500分兑换300元礼品,   500分以上兑换400元礼品
因为系统中有大量类似这样的规则,而且规则会经常变动,另外业务上也要求这样的规则最好能由业务人员自己定义和修改,因此一个很自然的考虑是使用规则引擎来实现。
二、现有规则引擎产品分析
最初希望使用商业或开源的规则引擎,但从网上搜索的关于规则引擎的资料来看,现有规则引擎实现这样的应用好象不太合适。
1、如何定义规则?
一般规则引擎中定义规则的方式如下:
代码
if {       规则   }   then {       动作   }
但这样的规则“消费1元人民币积1分”使用if...then...该如何定义呢?好象没法定义。
另外感觉这类规则定义就是一系列的if...then...这其中的逻辑和我们在java中的逻辑没有什么区别,
只是换了一种形式而已。这样的规则根本没办法给业务人员使用。
2、如何处理数据库与规则引擎的关系?
再者规则引擎是基于事实进行推演,所以在触发规则引擎计算之前,需要先装入事实。基于JSR94的实现
多使用OO的方式,例如:
代码
loadRules(); // 装入规则   WorkingMemory workingMemory = businessRules.newWorkingMemory();   workingMemory.addEventListener(new DebugWorkingMemoryEventListener());   workingMemory.assertObject(student); // 装入事实   workingMemory.fireAllRules(filter); // 触发计算
摘自http://www.blogchinese.com/06042/201878/archives/2006/200652418217.shtml
这里就有一个问题,如果我的事实是基于数据库记录,那么该如何装入事实?因为规则的定义中条件部分
一般是基于对象的属性,动作部分一般是基于对象的方法,所以如果事实能使用数据记录,那么条件特别是
动作该如何定义?
3、需要Rete算法吗?
只要对规则引擎稍有接触,应该都听说过“Rete算法”,现有的商业或开源的规则引擎多是基于该算法。多数会解决
这样一个问题,就是自动处理动作对事实的反馈,如果一个动作影响了事实,那么会重新针对事实过滤规则,我想这样的反馈
计算可能大大影响了规则引擎的性能,而正Rete算法解决了规则引擎的性能问题。但上述规则并不需要这样的特性,所以性能问题不会表现在这些方面。
因为对这类商业和开源的规则只是有一个泛泛的了解,不知其能否解决这些问题?怎样解决这些问题?
三、方案
终合上述考虑,决定自己实现规则引擎,首要的就是将上述语句表示为规则引擎能识别的规则,自然需要一套语法来定义这样的规则,
结合实现及面向业务人员这样的需求,大略将上述语句转换为如下规则定义:
代码
客户积分 += POS消费总额(商户类型!=汽车类|房地产类) {主体=XX信用卡客户}    客户积分 += POS消费总额(商户类型=汽车类)/ 100 * 6 {主体=XX信用卡客户}    客户积分 += POS消费总额(商户类型=房地产类)/ 100 * 8 {主体=XX信用卡客户}    客户积分 -= 如果(兑换奖品总额>=400,500) {主体=XX信用卡客户,扣减规则=(消费类型=退货)}    客户积分 -= 如果(兑换奖品总额>=300,300) {主体=XX信用卡客户,扣减规则=(消费类型=退货)}    客户积分 -= 如果(兑换奖品总额>=150,100) {主体=XX信用卡客户,扣减规则=(消费类型=退货)}
个人感觉如果能这样定义规则的话业务人员应该很容易就能看懂,也能很容易修改。
针对上述实现,我提出以下要求:
代码
语法简单,业务人员很容易明白   必须支持中文规则定义   必须支持自定函数(我想象的"POS消费总额","如果"都是函数)   很容易扩展函数   最好=,>,<之类的符号可以支持全角字符
四、实现
现在考虑如果要用程序实现上述规则,有以下两种方案:
1、使用动态脚本语言实现规则解析,如ruby, groovy,jaskell之类的(好象这就叫DSL吧),但
不知能不能满足我上面提出的要求。
2、使用javacc,antlr定义语法生成解析器。
第二种方案的好处是灵活性足够强,而且能满足“中文定义”的要求,但要权衡,维护和调试一个解析器也不是一件轻松的事。
原文出处:http://www.javaeye.com/article/25215?page=3