1. 程式人生 > >Drools一個很好的例子

Drools一個很好的例子

轉自http://www.360doc.com/content/15/0701/15/5054188_481943680.shtml

一、問題描述

假設僱員 Employ 有:

           學歷資訊 eduInfo , 簡歷資訊 resume ,

           考核資訊 annualExam 和獎懲資訊  awardPunish ;

要確定其:

           基本工資 basicSalary ,職務工資 dutySalary ,

           分紅金額 bonus 和 總工資 totalSalary .

規則如下:

【 1 】學歷決定基本工資( basicSalary ):

                       ====> 本科 1500 研究生 2500

【 2 】簡歷決定職務工資 (dutySalary) :

                       ====> 技術 2000 管理 4500

【 3 】年度考核決定分紅 (bonus) :

                       ====> 分紅總金額 1000

                       ==> 考核結果:

                        ==> 優秀 100% ( 1000 );良好 90% ( 900 );

                                       合格 60% ( 600 ); 不合格 0% ( 0 );

【 4 】獎懲決定計算最終工資與【 123 】項工資之和的比例:

                       ====> 獎勵: * 110% ( +10% )

                       ====> 懲罰: * 90% ( -10% )

                       ====> 無: * 100% ( 0% )

【 5 】計算總工資: (【 1 】 + 【 2 】 + 【 3 】) * 【 4 】

二、問題分析

1. 基本流程:

P 【計算基本工資,計算職務工資,計算分紅, 計算獎懲比例】

                    ====> 計算總工資 ( 根據獎懲情況 )

其中, P[i,...,k] 表示任務 i,...,k 併發執行, ====> 表示順序執行。

即有: P[1,2,3, 4] ===> 5

三、概要設計

【 1 】類 Employ 的設計:

【 2 】規則檔案的編寫和組織:

                ==> 學歷規則檔案: EduInfoRule.drl

                ==> 簡歷規則檔案: ResumeRule.drl

                ==> 分紅規則檔案: BonusRule.drl

                ==> 獎懲規則檔案: AwardPunish.drl

                ==> 計算總工資規則: TotalRule.drl

【 3 】規則檔案的組合(規則流):

                 ==> EduInfo.drl 含規則組 basic_salary

                 ==> ResumeRule.drl 含規則組 duty_salary

                 ==> BonusRule.drl 含規則組 bonus_salary

                 ==> AwardPunish.drl 含規則組 award_punish

                  ==> TotalRule.drl 含規則組 sum_salary

組合方式:

[start] --->  P[ basic_sal ary , duty_salary, bonus_salary, award_punish ]

                  ---> sum_salary ---> [end]

其中: P 表示併發, ---> 表示順序 【規則流圖在後面的實現中給出】

【 4 】編寫測試檔案: EmployTest.java

四、詳細設計

【 1 】使用 Eclipse IDE 作為開發環境, drools5.1 作為規則引擎

【 2 】 為簡單起見, Employ 類的屬性作了簡化處理,

              eduInfo , resume , annualExam,   awardPunish 均為 String ,

                   basic{duty,bonus, total}_salary , percent 作為 double 型別。

五、規則檔案及規則流

               EduInfoRule.drl :

package myrules;


import sample.Employ;

rule "Bachelor"

       ruleflow-group "basic_salary"


when

   emp: Employ(eduInfo == "bachelor" );

then

   System.out.println( "exec rule Bachelor ... " );

   emp.setBasicSalary(1500);

end


rule "Master"

       ruleflow-group "basic_salary"


when

   emp: Employ(eduInfo== "master" )

then

   System.out.println( "exec rule Master ... " );

   emp.setBasicSalary(2500);

end


              Resume.drl


package myrules

import sample.Employ;


rule "Technician"

        ruleflow-group "duty_salary"


when

   emp: Employ(resume== "tech" )

then

   System.out.println( "exec rule Technician ... " );

   emp.setDutySalary(2000);

end


rule "Manager"

       ruleflow-group "duty_salary"


when

   emp: Employ(awardPunish== "manager" )

then

   System.out.println( "exec rule manager ... " );

   emp.setDutySalary(4500);

end


               BonusRule.drl


package myrules


import sample.Employ;

rule "Excellent"

       ruleflow-group "bonus_salary"


when

   emp: Employ(annualExam== "excellent" )

then

   System.out.println( "exec rule Excellent ... " );

   emp.setBonus(1000*1.0);

end


rule "Good"

        ruleflow-group "bonus_salary"

when

   emp: Employ(annualExam== "good" )

then

   System.out.println( "exec rule Good ... " );

   emp.setBonus(1000*0.9);

end


rule "Common"

       ruleflow-group "bonus_salary"


when

   emp: Employ(annualExam== "common" )

then

   System.out.println( "exec rule Common ... " );

   emp.setBonus(1000*0.6);

end


rule "failing"

        ruleflow-group "bonus_salary"


when

   emp: Employ(annualExam== "failing" )

then

   System.out.println( "exec rule failing ... " );

   emp.setBonus(1000*0.0);

end


               AwardPunish.drl


package myrules


import sample.Employ;


rule "Award"

        ruleflow-group "award_punish"


when

   emp: Employ(awardPunish== "award" )

then

   System.out.println( "exec rule Award ... " );

   emp.setPercent(1.10);

end


rule "Punishment"

        ruleflow-group "award_punish"

when

   emp: Employ(awardPunish== "punish" )

then

   System.out.println( "exec rule Punishment ... " );

   emp.setPercent(0.90);

end


rule "None"

       ruleflow-group "award_punish"


when

   emp: Employ(awardPunish== "none" )

then

   System.out.println( "exec rule None ... " );

   emp.setPercent(1.00);

end

               TotalRule.drl


package myrules

import sample.Employ;


rule "Total"

   ruleflow-group "sum_salary"


when

   emp: Employ()

then

   System.out.println( "exec rule Total ... " );

   double total = emp.getBasicSalary() +  emp.getDutySalary() +


                  emp.getBonus();                                  

   emp.setTotalSalary(total*emp.getPercent());

end

                建立規則流檔案 simple.rf :

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />  Java Drools5.1 規則流基礎【示例】 -  大雨 - 大雨的部落格
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
 

注意:

        [1] Split 結點型別為 OR ,約束選擇 always true. 表示選擇其規則組中所有符合事實的規則進行併發執行;

        [2] Join 結點型別為 AND ,表示當且進當上述規則組均執行完畢後,才執行後面的規則或程序。

 Java Drools5.1 規則流基礎【示例】 -  大雨 - 大雨的部落格

六、測試程式碼:

Employ:

package sample;


public class Employ {

public static final double BONUS = 1000;


private String eduInfo ;

private String resume ;

private String annualExam ;

private String awardPunish ;


private double basicSalary ;

private double dutySalary ;

private double bonus ;

private double percent ;


private double totalSalary ;


// getter/setter methods


public String toString() {

return "[" + eduInfo + " " + resume + " " + annualExam +

" " + awardPunish + " " + basicSalary + " " + dutySalary +

" " + bonus + " " + totalSalary + "]" ;

}


}


EmployTest:


package sample;


import org.drools.KnowledgeBase;

import org.drools.KnowledgeBaseFactory;

import org.drools.builder.KnowledgeBuilder;

import org.drools.builder.KnowledgeBuilderError;

import org.drools.builder.KnowledgeBuilderErrors;

import org.drools.builder.KnowledgeBuilderFactory;

import org.drools.builder.ResourceType;

import org.drools.io.ResourceFactory;

import org.drools.logger.KnowledgeRuntimeLogger;

import org.drools.logger.KnowledgeRuntimeLoggerFactory;

import org.drools.runtime.StatefulKnowledgeSession;


public class EmployTest {


public static void main(String[] args) {


try {

// load up the knowledge base

KnowledgeBase kbase = readKnowledgeBase();

StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();

KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");

// go !

Employ emp = new Employ();

emp.setEduInfo("master");

emp.setResume("tech");

emp.setAnnualExam("good");

emp.setAwardPunish("award");

ksession.insert(emp);

ksession.startProcess("myrules.salary");

ksession.fireAllRules();

System.out.println("Basic Salary: " + emp.getBasicSalary());

System.out.println("Duty Salary: " + emp.getDutySalary());

System.out.println("Bonus : " + emp.getBonus());

System.out.println("rate : " + emp.getPercent());

System.out.printf("Total Salary: %.0f" , emp.getTotalSalary());

logger.close();

} catch (Throwable t) {

    t.printStackTrace();

}


}


private static KnowledgeBase readKnowledgeBase() throws Exception {

KnowledgeBuilder kbuilder =

KnowledgeBuilderFactory.newKnowledgeBuilder();

kbuilder.add(ResourceFactory.newClassPathResource("EduInfoRule.drl"), ResourceType.DRL);

kbuilder.add(ResourceFactory.newClassPathResource("ResumeRule.drl"), ResourceType.DRL);

kbuilder.add(ResourceFactory.newClassPathResource("BonusRule.drl"), ResourceType.DRL);

kbuilder.add(ResourceFactory.newClassPathResource("AwardPunish.drl"), ResourceType.DRL);

kbuilder.add(ResourceFactory.newClassPathResource("TotalRule.drl"), ResourceType.DRL);

kbuilder.add(ResourceFactory.newClassPathResource("salary.rf"), ResourceType.DRF);

KnowledgeBuilderErrors errors = kbuilder.getErrors();

if (errors.size() > 0) {

    for (KnowledgeBuilderError error: errors) {

        System.err.println(error);

    }

    throw new IllegalArgumentException("Could not parse knowledge.");

}

KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());

return kbase;

}


}

              測試結果:

               exec rule Technician ...

            exec rule Master ...

exec rule Good ...

exec rule Award ...

exec rule Total ...

Basic Salary: 2500.0

Duty Salary: 2000.0

Bonus : 900.0

rate : 1.1

Total Salary: 5940

七、總結


Java drools 規則流基礎:


【 1 】掌握規則引擎的基本工作原理;

【 2 】掌握規則檔案的編寫;

【 3 】掌握規則流圖的繪製及應用程式整合。

【 4 】掌握規則組合的兩種基本方式【併發和順序】的實現方式。


下一步:


【 1 】更復雜的規則組合;

【 2 】規則檔案的組織、管理;

【 3 】規則檔案的自動生成;

【 4 】使用者自定義規則;