本文用Drools 解决喝啤酒问题。
本文结构如下:
1. 规则
2. 通过业务式编程 实现
3. 通过drools 规则引擎实现
规则:
//喝啤酒问题,小明去喝啤酒,啤酒搞活动,
// 啤酒二元一瓶,
// 两个空瓶可以再换一瓶啤酒,
// 四个瓶盖也可以换一瓶啤酒,
// 问小明花多少钱可以喝多少瓶啤酒?
通过业务式编程。代码实现:
public class DrinkBeerTest { public static void main(String[] args) { System.out.println("请输入买啤酒的总金额:"); Scanner sc = new Scanner(System.in); int money = sc.nextInt(); int drinkSum = 0, blankCup = 0, cap = 0; //drinkSum:喝的瓶数 drinkSum = money / 2; //cap:瓶盖数 ,blankCup:空瓶数 cap = blankCup = drinkSum; while (cap / 4 >= 1 || blankCup / 2 >= 1) { if (blankCup / 2 >= 1)//计算瓶子 { drinkSum += blankCup / 2; cap = cap + blankCup / 2; blankCup = blankCup % 2 + blankCup / 2; } if (cap / 4 >= 1) { //计算瓶盖 drinkSum += cap / 4; blankCup += cap / 4; cap = cap % 4 + cap / 4; } } System.out.println("总共喝啤酒数" + drinkSum + " 剩余空瓶数:" + blankCup + " 剩余瓶盖数:" + cap); } }
结语:代码嵌套层次多,复杂,语义晦涩难懂,不便理解。且规则变化,可复用性低。
3. 通过Drools 实现
3.1 pojo
用作drools 的fact
package com.us.drink; /** * Created by yangyibo on 16/12/13. * * 饮酒客户 */ public class Customer { private String name; private int money; private int drinkSum; private int blankCup; private int cap; public Customer(String name, int money) { super(); this.name = name; this.money = money; this.drinkSum = 0; this.blankCup = 0; this.cap = 0; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } public int getDrinkSum() { return drinkSum; } public void setDrinkSum(int drinkSum) { this.drinkSum = drinkSum; } public int getBlankCup() { return blankCup; } public void setBlankCup(int blankCup) { this.blankCup = blankCup; } public int getCap() { return cap; } public void setCap(int cap) { this.cap = cap; } @Override public String toString() { return this.name+"同学还有" +this.money+"元钱,喝了"+this.drinkSum+"瓶酒, 有" +this.getBlankCup()+"个空瓶和" +this.getCap()+"个盖子"; } }
3.2 rules 规则文件
drinkRules.drl 文件
package com.us.drink; import com.us.drink.Customer; rule "buy a beer and drink" salience 1 when $c: Customer(money >= 2,$m:money,$b:blankCup,$d:drinkSum,$a:cap); then $c.setMoney($m-2); $c.setBlankCup($b+1); $c.setDrinkSum($d+1); $c.setCap($a+1); System.out.println($c.toString()); update($c); end rule "sale blank cup get a beer" salience 3 when $c : Customer(blankCup>=2,$b:blankCup,$d:drinkSum,$a:cap); then $c.setBlankCup($b-1); $c.setDrinkSum($d+1); $c.setCap($a+1); System.out.println($c.toString()); update($c); end rule "sale cap and get a beer" salience 2 when $c : Customer(cap>=4,$b:blankCup,$d:drinkSum,$a:cap); then $c.setCap($a-3); $c.setBlankCup($b+1); $c.setDrinkSum($d+1); System.out.println($c.toString()); update($c); end rule "finish drink" dialect "java" when $c:Customer(blankCup < 2,money < 2,cap< 4); then System.out.println("finish drink"+$c.toString()); end
3.3 kmodule.xml
如果没有 kmodule.xml 文件,在META-INF 文件夹下新建kmodule.xml 文件填写如下内容
<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> <!--喝啤酒--> <kbase name="DrinkBeerKB" packages="com.us.drink"> <ksession name="DrinkBeerKS"/> </kbase> </kmodule>
3.4 drinkTest
package com.us.drink; import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; /** * Created by yangyibo on 16/12/13. */ public class DrinkBeer { private static KieSession getSession() { KieServices ks = KieServices.Factory.get(); KieContainer kc = ks.getKieClasspathContainer(); return kc.newKieSession("DrinkBeerKS"); } private static void drink() { KieSession ks = getSession(); Customer c1 = new Customer("奥巴马", 10); ks.insert(c1); int count = ks.fireAllRules(); System.out.println("总执行了" + count + "条规则"); System.out.println(c1.toString()); } public static void main(String[] args) { drink(); } }
结语:通过drools 实现,规则信息,清晰易读。且规则灵活可随意修改,做到了规则和数据分离。提高了代码的可读性和可维护性。
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/15223.html