I have a requirement which take lots of rules validated against the java value objects and produces results. (we cant use any rule engine apps in our company, lots of formalities and lots of questions to be answered). So, rather than implementing the rules as ifs' in java code I suggested to implement a small rule engine, Simple and Extensible. Which design pattern to follow?
I have added below a rough xml structure of the rules defined.
<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>
It really depends on the complexity of the rules you are trying to implement. The key idea in declarative programming is that rules are treated as data. So, the simplest way to start is to see if all your rules can be represented as data in a table. For instance, if your rules are of the type if a=10, then b = 7, then you can represent the same in a table and write a generic method that can handle all your cases.
On the other hand, if your rules allow multiple conditions (and/or clauses as well as comparison operators), a table based design will not help.
In that case, you need to specify the grammar for your rules, generate a lexer and a parser. The parser would parse your actual rules into a abstract syntax tree. Once you get to that stage, you can either take that tree and target it to an existing rule engine or your own rule engine that knows how to execute the tree.