我有一个要求,它需要对java值对象进行大量验证并生成结果。 (我们不能使用我们公司的任何规则引擎应用程序,许多手续和许多问题需要回答)。 因此,我建议实现一个简单和可扩展的小规则引擎,而不是像在java代码中那样实现规则。 要遵循哪种设计模式?
我在下面添加了定义规则的粗略xml结构。
<rule-set>
<name>Example1</name>
<description>Example rules defined</description>
<beans>
<bean class="com.example.Customer" alias="cust"/>
<bean class="com.example.Account" alias="acnt"/>
<bean class="com.example.Transaction" alias="trans"/>
</beans>
<rule name="CustomerInfo" description="This rule validates if all the customer values are present">
<if lhs="cust.getFirstName" rhs="null" operator="!="/>
<if lhs="cust.getLastName" rhs="null" operator="!=" logicaloperator="&&"/>
<if lhs="cust.getCountry" rhs="null" operator="!=" logicaloperator="||"/>
<if lhs="cust.getCity" rhs="null" operator="!=" logicaloperator="&&"/>
<if lhs="cust.getPhone" rhs="null" operator="!=" logicaloperator="&&"/>
<if lhs="cust.getEmail" rhs="null" operator="!=" logicaloperator="&&"/>
<then do="cust.completeFlag" arg1="true"/>
</rule>
<rule name="Transaction" description="Transfer the money from one ac to another">
<if lhs="trans.fromAccount" operator="!=" rhs="null"/>
<if lhs="trans.toAccount" operator="!=" rhs="null"/>
<if lhs="trans.fromAccount.balance" operator=">" rhs="trans.getTransaferAmount"/>
<then do="trans.fromAccount.debit" arg1="trans.getTransaferAmount"/>
<then do="trans.toAccount.credit" arg1="trans.getTransaferAmount"/>
</rule>
</rule-set>
答案 0 :(得分:4)
这实际上取决于您尝试实施的规则的复杂性。声明性编程的关键思想是将规则视为数据。因此,最简单的方法是查看是否所有规则都可以表示为表中的数据。例如,如果你的规则是a = 10的类型,那么b = 7,那么你可以在表中表示相同的规则,并编写一个可以处理所有情况的通用方法。
另一方面,如果您的规则允许多个条件(和/或子句以及比较运算符),则基于表的设计将无济于事。
在这种情况下,您需要为规则指定语法,生成词法分析器和解析器。解析器会将您的实际规则解析为抽象语法树。进入该阶段后,您可以获取该树并将其定位到现有规则引擎或您自己的知道如何执行树的规则引擎。
答案 1 :(得分:0)
我会推荐一个Factory Method Pattern。每个规则都有一个可以创建这些规则的Factory。然后我会将所有这些规则工厂封装成Abstract Factory。
或者,您可以将规则引擎创建为构建器(使用Builder Pattern),以允许传递规则集并构建规则。
这就是我最擅长的,但是因为我不知道你的规则引擎的确切要求会让人想到什么。
也许Strategy Pattern可以帮到你?
答案 2 :(得分:0)
不完全是你提出的问题(即模式),但如果你想自己推出,可能会发现以下方法很有用:
http://mcqueeney.com/blog/creating-a-simple-rules-engine-using-the-java-scripting-api/