Drools -喝啤酒问题详解编程语言

本文用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

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论