Fork me on GitHub

小L 的个人博客

生活虽不能自由,但愿心能自由。

  menu
10 文章
0 评论
17075 浏览
0 当前访客
ღゝ◡╹)ノ❤️
生活虽不能自由,但愿心能自由

Drools规则详解

    1. DRL文件组成
    package
    import
    function(可选)
    query(可选)
    declare(可选)
    global(可选)
    rule "rule name" 
     	// Attributes 
    	when // Conditions
    	then // Actions 
    end
    
     一个规则文件可以包含多个规则、查询、函数和定义的资源声明如global、import、attributes等,package必须在顶部列出。每个规则必须有唯一的规则名称在一个package下,否则将编译错误。 相同package下的资源默认导入。其它package下可以通过import来导入。
    

    1.1 package
    package必须具有名称,并使用Java标准声明包名称。例如:package com.lei2j.test.User;
    1.2 import
    同Java中import类似,导入的对象要全路径和对象名称。以packageName.objectName导入,可以多行导入。同样,Drools引擎同样会导入鱼DRL包同名的Java Package和Java.lang.*。
    1.3 function
    Function在DRL文件中编写代码替代了在Java类中编写。这个在多个规则执行同一套代码(只是参数不一样)甚好。也可以在规则文件中导入Java静态方法作为Function。

    function String hello(String name){
      return "Hello"+name;
    }
    
    rule "Hello function"
    when 
      //todo
    then 
     System.out.println(hello("lei2j"));
    

    1.4 query

    1.5 declare
    在DRL文件中可以定义新的Fact类型或Metadata作为作为Facts Type被规则使用。
    New fact types: 你可以不需要再Java语言中定义Fact。可以在已有的Fact基础上补充定义Fact。
    Metadata for fact types: 可以将**@key(value)**格式的元数据关联到新的或已存在的Fact上。
    1.5.1 无Metadata的Fact的定义
    新的Fact定义可以不需要任何Metadata,但是必须包含字段或属性。若一个Fact type 定义不包含任何标识性属性,则Drools引擎会搜索已存在的Fact类在classpath下,若class缺失则会引发错误。
    例如:

    declare Person
       name:String
       age:Integer
       brithday:java.util.Date
       address:Address
    end
    rule "Use Declared Person type"
       when
         $p : Person(name == "Jack")
        then
           Person mark = new Person();
           mark.setName("Mark");
           insert(mark);
    end
    

    在上面的例子上,定义了一个新的类型Person,并定义了name、age、brithday和address等属性列表,属性的类型可以是任何有效的Java类,或者你已经定义的Fact type,其中brithday属性的类型是java.util.Date,address属性的类型是提前定义的Address类。未来避免书写属性类型限定名称,可以使用import导入需要的类。
    如:import java.util.Date
    定义的新Fact类型后,Drools会在编译时生成对应的符合JavaBean规范的Model类。
    例如:

    public  class Person implements Serializable { 
      private String name; 
      private java.util.Date dateOfBirth; 
      private Address address; 
     // Empty constructor  public Person() {...}
     // Constructor with all fields  public Person( String name, Date dateOfBirth, Address 
     address ) {...} 
     // If keys are defined, constructor with keys  
     public Person( ...keys... ) {...}
     // Getters and setters  
     // `equals` and `hashCode`  
     // `toString` 
    }
    

    1.5.2 枚举类定义
    使用格式**declare enum ,接着以","分隔的值列表,以分好结尾。
    例如:

    declare enum DayOfWeek
    SUN("Sunday"),MON("Monday"),TUE("Tuesday"),WED("Wednesday"),THU("Thursday"),FRI("Friday"),SAT("Saturday");
    
    name: String
    end
    
    rule "Print DayOfWeek name"
      when 
       $day : DayOfWeek()
      then  
         System.out.pringln("print:"+$day.getName());
    end
    

    1.5.3 扩展类型定义
    DRL中以格式**declare <childFactType> extends <parentFactType>**来声明继承,若需要继承Java中声明的类,则需要在DRL中重复声明所需要继承Java中父类。
    例如:

    import com.lei2j.Person //导入Java中的定义类
    declare Person  //定义跟Java类相同的名称
    end
    declare School extends Person
       school : String
    end
    declare LongTermStudent extends Student
     years : int
     course : String 
    end
    
    

    1.5.4 带元数据的类型定义
    可以将格式@key(value)的元数据与Fact或属性相关联。在Fact属性前的声明的元数据将分配给该Fact,而在属性后声明则被分配给特定属性。
    例如:

    import java.util.Date
    declare Person 
    	@author(lei)
    	@dateOfCreation(01-01-2020)
    	
    	name : String @key @maxLength(19)
    	dateOfBirth : Date
            address : Address
    end
    

    以上例子展示了元数据属性@author和@dateOfCreation是被定义在Person Fact,而元数据属性@key和@maxLength是被定义在Person Fact 的name字段上。
    对于已存在的Fact类型,可以使用完全限定名定义其元数据属性。
    例如:

    import com.lei2j.Person;
    
    declare Person
     	@author(lei)
    	@dateOfCreation(01-01-2020)
    
    

    1.5.5 元数据标签在Fact type和属性上的定义

    1.5.6 Fact type的属性更改设置和监听

    1.5.7 应用程序中访问在DRL文件中定义的Fact
    若要直接从应用程序代码中访问规则文件中声明的类型,可以使用org.drools.definition.type.FactType API,通过此API,可以实例化、读写字段。
    例如:

    KieBase kbase;
    FactType factType = kbase.getFactType(packageName,FactName);
    Object ins = factType.newInstance();
    factType.set(ins,"field",value);
    
    

    1.6 全局变量(Global variables)定义
    Global variables在DRL中通常提供数据或服务,定义了Global variables后,可以在RHS中使用它。
    例如:

    List<String> list = new ArrayList<>(); 
    EmailService emailService;
    KieSession kieSession = kiebase.newKieSession(); 
    kieSession.setGlobal( "myGlobalList", list );
    kieSession.setGlobal("emailService",emailService);
    
    import java.util.List;
    global List myGlobalList;
    global EmailService emailService;
    
    rule "Using a global"
    	when
               //condition
            then
              myGlobalList.add("str");
              emailService.sendMsg("xxxx");
    end
    

    注意:不要在LHS中使用全局变量,Global variables不是存在于working memory中。也无法追踪Global variables的值改变。不要使用Global variables作为规则之间的数据传递,如果需要请作为Fact插入working memory中。
    1.7 规则属性
    规则属性可以添加到业务规则中以修改规则行为。在DRL文件中,通常在LHS和RHS上方定义规则属性。
    例如:

    rule "rule_name"  
    // Attribute  
    // Attribute
     when 
    	// Conditions 
      then 
    	// Actions 
    end
    

    Attribute Value
    salience 规则优先级,数字越大越优先执行。例如:salience 10
    enabled 是否禁用规则,默认启用。例如:enabled true
    date-effective 日期时间定义。当且仅当在到达该日期规则才会激活。例如:date-effective "4-Sep-2018"
    date-expires 日期时间定义。在该日期之前(包含)才会激活规则。例如:date-expires "4-Oct-2018"
    no-loop 若为true时,规则结果重新触发了先前满足的规则条件,则无法重新激活(循环)规则。否则,可以重复执行。
    agenda-group给规则分配一个agenda group 标识。允许你更好地控制组内规则,只有已获得agenda group中的规则才能被激活。例如:agenda-group "GroupName"
    activation-group分配给规则的activation (or XOR) group。在同一个activation group中,只有一个规则被激活执行。组内顺序按salience属性排序。例如:activation-group "GroupName"
    duration在一个规则持续满足规则条件时,定义规则被激活后持续时间(以毫秒为单位)。例如:duration 10000
    timer用于调度规则的int(间隔)或cron计时器定义。例如:timer ( cron:* 0/15 * * * ? )
    calendar基于Quartz的定时器定义。例如:calendars "* * 0-7,18-23 ? * *"
    auto-focus仅为适用于agenda groups。为true时,下次激活该规则时,焦点自动分配给该规则的agenda groups。例如:auto-focus true
    ruleflow-grouprule flow group字符串标识。在该组中,只有在关联的rule flow激活该组时,该组规则才能触发。例如:ruleflow-group "GroupName"
    dialectJAVAMVEL标识为规则中用于代码表达式的语言。例如:dialect "JAVA"
    lock-on-active 布尔值。仅用于rule flow groups或agenda groups。

    为true时,下次rule flow groups变为激活状态时或agenda group获得焦点时,rule flow groups和agenda group无法再次激活该规则。
    这是no-loop属性的增强版本。因为再次匹配的规则激活会被丢弃。
    此属性适用于计算规则的类型,在计算规则中,有许多修改Fact的规则,并且不希望任何规则重新匹配并再次触发。例如:lock-on-active true|


    1.7.1 规则属性timer和calendar
    timer属性可以使用字符串标识的int(时间间隔)或cron定时器用于规则的调度。
    timer格式

    timer ( int: <initial delay>  <repeat interval> )
    
    timer ( cron: <cron expression> )
    

    例如:

    timer(int : 20s )//20s后执行
    timer(int : 15s 60s)//15s后首次执行,每隔60s执行一次
    timer(cron : * 0/15 * * * ?)//每隔15min执行一次
    

    间隔定时器遵循java.util.Timer对象语义。Cron定时器遵循标准的unix表达式。
    例如:

    rule "Send SMS message every 15 minutes" 
    timer ( cron:* 0/15 * * * ? ) 
    when 
    	$a : Alarm( on == true ) 
    then 
    	channels[ "sms" ].insert( new Sms( $a.mobileNumber, "The alarm is still on." );
    end
    

    通常,根据计时器设置,当触发规则并重复执行规则结果时,由计时器控制的规则会激活。当规则条件不在匹配时,执行将停止。但是,计时器处理规则方式取决于Drools引擎处于active mode(主动模式)还是passive mode(被动模式)。
    默认,当调用fireAllRules()时,Drools引擎处于passive mode并评估规则。若调用fireUntilHalt(),则Drools引擎将以active mode并持续评估规则,直至调用halt()为止。
    当Drools引擎处于active mode时,即使从fireUntilHalt()调用返回后,规则结果也会执行,并且也会对Facts的任何更改作出反应。例如:删除计时器规则涉及的Fact好导致重复执行中止,插入一个Fact会使某些规则匹配导致规则被执行。但是,Drools引擎不会持续激活,只有在执行规则后才会激活。所以,在没有执行计时器规则之前,Drools不会对异步Fact插入做出反应。
    对于间隔计时器,还可以将表达式计时器和expr一起使用,而不是用int来将延迟和间隔定义为表达式。
    例如:

    declare Bean 
    	delay : String = "30s"  
    	period : long = 60000  
    end 
    rule "Expression timer" 
    timer ( expr: $d, $p ) 
    	when 
    	  Bean( $d : delay, $p : period )
      	then 
    	  // Actions 
    end
    

    可以使用在规则的模式匹配部分中定义的任何变量。
    时间间隔计时器和表达式计时器都可以使用以下可选参数:
    * startandend:代表日期或长值的日期或字符串。该值也可以是一个数字。
    * repeat-limit:最大重复执行次数。若同时设置了endrepeat-limit,则首先达到2者中的一个时,计时器将停止。
    例如:

    timer (int: 30s 1h; start=3-JAN-2020, end=4-JAN-2020, repeat-limit=50)
    

    calendar属性遵循Quartz calendar定义。calendar属性可以包含一个或多个用字符串文字表示的逗号分隔的日历名称
    格式:

    calendars "<definition or registered name>"
    

    例如:

    // Exclude non-business hours 
    calendars "* * 0-7,18-23 ? * *"
    // Weekdays only, as registered in the KIE session 
    calendars "weekday"
    

    calendars和timers一起混合使用。例如:

    rule "Weekdays are high priority"
    calendars "weekday" 
    timer ( int:0  1h ) 
    	when 
    		Alarm() 
    	then 
    		send( "priority high - we have an alarm" ); 
    end 
    rule "Weekends are low priority" 
    calendars "weekend" 
    timer ( int:0  4h ) 
    	when 
    		Alarm() 
    	then 
    		send( "priority low - we have an alarm" ); 
    end
    
    

    1.8 规则条件(when)
    规则的when条件部分(LHS)包含执行操作的必要条件,条件由一些模式和约束组成,以及可选的对象绑定和关键字组成。
    如果when为空,则默认为true,将执行then中的动作。
    例如:

    rule "Always insert applicant"  
    	when  
    		// Empty 
    	then  
    		// Actions to be executed once 
    		insert( new Applicant() ); 
    end 
    // The rule is internally rewritten in the following way: 
    rule "Always insert applicant"  
    	when 
    		eval( true ) 
    	then 
    		insert( new Applicant() );
    end
    
    

    若条件使用多个模式,但没有关键字连接,则默认使用关键字and连接:

    rule "Underage"  
    	when 
    		application : LoanApplication() 
    		Applicant( age < 21 ) 
    	then  
    		// Actions 
    end 
    // The rule is internally rewritten in the following way: 
    rule "Underage" 
     	when 
    		application : LoanApplication() 
    		and 
    		Applicant( age < 21 ) 
    	then 
    	 	// Actions 
    end
    
    

    1.8.1 模式和约束
    模式是Drools引擎要匹配的段。模式默认匹配working memory中的每个fact。模式还可以包含约束。以近一步约束要匹配的fact。

    Pattern
    最简单的模式匹配给定的Fact类型:

    Person()
    

    模式不必是某个具体的类型,可以是其超类甚至接口。

    Object() // 匹配的所有的插入的fact
    

    带有约束的模式匹配:

    Person( age == 50 )
    

    Drools引擎会缓存访问Fact属性值的结果。
    你可以在模式中访问嵌套属性。
    例如:

    Person( address.houseNumber == 50 )
    

    注意:在stateful KIE sessions中,当心使用嵌套属性访问器,因为这将不会检测到任何嵌套属性的更改,若要修改,需要将所有外部fact标记为已更新。
    可以在约束中使用Java类方法,例如:

    Person( Math.round( weight / ( height * height ) ) < 25.0 )
    

    对于多组约束,可以使用","来连接表示为and
    例如:

    // Person is at least 50 years old and weighs at least 80 kilograms: 
    Person( age > 50, weight > 80 )
    // Person is at least 50 years old, weighs at least 80 kilograms, and  is taller than 2 meters: 
    Person( age > 50, weight > 80, height > 2 )
    

    在一个约束中,",“和and&&不能混用。并且”,"不能在符合表达式中使用。
    例如:

    //错误,应将","换成"&&"
    Person( ( age > 50, weight > 80 ) || height > 2 )
    
    

    1.8.2 模式和约束的变量绑定
    你可以将变量绑定到模式和约束,以引用规则匹配的对象。
    例如:

    rule "simple rule"  
    	when 
    		$p : Person() 
    	then 
    		System.out.println( "Person " + $p ); end
    

    以上将变量$p绑定于Person fact。
    类似,你也可以将变量绑定到属性在模式约束中。

    // Two persons of the same age: 
    Person( $firstAge : age ) // Binding 
    Person( age == $firstAge ) // Constraint expression
    

    1.8.3 嵌套约束和强制转换

    Person( name == "mark", address.city == "london", address.country == "uk" )
    

    对于访问嵌套对象的多个属性,可以使用语法.( <constraints> )简化访问。如:

    Person( name == "mark", address.( city == "london", country == "uk") )
    

    当需要访问嵌套对象时,可以使用语法<field>#<subClassType>强制转换为子类型。例如:

    // Inline casting with subtype name: 
    Person( name == "mark", address#LongAddress.country == "uk" )  
    // Inline casting with fully qualified class name: 
    Person( name == "mark", address#org.domain.LongAddress.country == "uk" )  
    // Multiple inline casts: 
    Person( name == "mark", address#LongAddress.country#DetailedCountry.population > 10000000 )
    

    你也可以使用instanceof运算符判断类型,再后续访问嵌套属性。如:

    Person( name == "mark", address instanceof LongAddress, address.country == "uk" )
    

    1.8.4 日期约束
    Drools引擎默认支持格式:dd-mmm-yyyy。你还可以使用系统属性drools.dateformat="yyyy-mm-dd hh:mm"
    1.8.5 模式约束支持的操作符
    模式约束中运算符支持标准Java语义,但有一些例外及一些特有的运算符。
    .(),#
    使用.()操作符访问嵌套属性,使用#操作符强制转换子类型。

    // Ungrouped property accessors: 
    Person( name == "mark", address.city == "london", address.country == "uk" ) 
    // Grouped property accessors: 
    Person( name == "mark", address.( city == "london", country == "uk") )
    // Inline casting with subtype name: 
    Person( name == "mark", address#LongAddress.country == "uk" )  
    // Inline casting with fully qualified class name: 
    Person( name == "mark", address#org.domain.LongAddress.country == "uk" )  
    // Multiple inline casts: 
    Person( name == "mark", address#LongAddress.country#DetailedCountry.population > 10000000 )
    

    !.
    此操作符可以null-safe方式取消引用属性,左侧值不能为null。

    Person( $streetName : address!.street ) 
    // This is internally rewritten in the following way: 
    Person( address != null, $streetName : address.street )
    
    

    []
    此操作符通过index访问List值或通过key访问Map。

    // The following format is the same as `childList(0).getAge() == 18`: 
    Person(childList[0].age == 18) 
    // The following format is the same as `credentialMap.get("jdoe").isValid()`:
    Person(credentialMap["jdoe"].valid)
    

    <,<=,>,>=
    适用于比较属性

    ==,!=
    等效于equals()and!equals()方法。
    &&,||
    matches,not matches
    匹配Java正则表达式。

    Person( country matches "(USA)?\\S*UK" ) 
    Person( country not matches "(USA)?\\S*UK" )
    

    contains,not contains
    此操作符可以验证数组或者集合是否包含指定值。也可以用于替换String.contains()and!String.contains()

    // Collection with a specified field: 
    FamilyTree( countries contains "UK" ) 
    FamilyTree( countries not contains "UK" ) 
    // Collection with a variable: 
    FamilyTree( countries contains $var ) 
    FamilyTree( countries not contains $var )
    
    // Sting literal with a specified field: 
    Person( fullName contains "Jr" ) 
    Person( fullName not contains "Jr" ) 
    // String literal with a variable: 
    Person( fullName contains $var ) 
    Person( fullName not contains $var )
    

    memberOf,not memberOf
    验证字段是否是变量(数组或集合)的成员。

    FamilyTree( person memberOf $europeanDescendants ) 
    FamilyTree( person not memberOf $europeanDescendants )
    

    soundslike
    验证是否与给定的单词具有与英语发音相近的发音。

    // Match firstName "Jon"  or  "John": 
    Person( firstName soundslike "John" )
    

    str
    验证String字段是否已指定值开始或结束,也可以验证其长度

    // Verify what the String starts with: 
    Message( routingValue str[startsWith] "R1" ) 
    // Verify what the String ends with: 
    Message( routingValue str[endsWith] "R2" )
    // Verify the length of the String: 
    Message( routingValue str[length] 17 )
    

    in,notin

    Person( $color : favoriteColor ) 
    Color( type  in ( "red", "blue", $color ) ) 
    
    
    Person( $color : favoriteColor ) 
    Color( type notin ( "red", "blue", $color ) )
    

    1.8.6 运算符优先级
    运算符从高到低顺序如下

    操作类型 操作符 解释
    嵌套或null-safe安全属性访问 .(),!. 非标准Java语法
    List或Map访问 [] 非标准Java语法
    约束绑定 : 非标准Java语法
    乘除*,/%
    加减+,-
    移位>>,>>>,<<
    比较操作符<,<=,>,>=,instanceof,==,!=
    &,|,^
    &&,||,^
    三元运算符? :
    逗号,等效于and和&&

    1.8.7 规则条件元素关键字
    and
    用于连接各个约束,并且所有约束都符合
    or
    用于连接各个约束,并且只要一个约束符合
    exists
    指定必须存在的Fact和约束。
    not
    forall
    from
    entry-point
    collect
    accumulate
    eval
    允许执行任何语义代码,返回布尔值。适合在函数返回值变化时使用,这在字段约束中不允许的。

    p1 : Parameter() 
    p2 : Parameter() 
    eval( p1.getList().containsKey( p2.getItem() ) )
    
    p1 : Parameter() 
    p2 : Parameter() 
    // call function isValid in the LHS 
    eval( isValid( p1, p2 ) )
    

    1.9 规则动作
    规则的后一部分(RHS)包含在满足条件部分时要执行的操作。
    RHS部分主要目的是在Drools引擎的working memory中insert、delete或upate Fact。
    如果RHS部分有命令性或条件性代码,则可以将规则分为更小的规则。

    rule "Underage" 
    	when 
    		application : LoanApplication() 
    		Applicant( age < 21 ) 
    	then 
    		application.setApproved( false ); 			 
    	        application.setExplanation( "Underage" ); 
    end
    

    1.9.1 支持的规则操作方法
    DRL支持以下在DRL规则操作中使用的规则操作方法。
    set
    它可以指定设置字段值。格式:

    set<field> ( <value> )
    

    例如:

    $application.setApproved ( false );
    $application.setExplanation( "has been bankrupt" );
    

    modify
    它可以用来为指定字段更新,并将更改通知给Drools引擎。格式:

    modify ( <fact-expression> ) { 
    <expression>, 
    <expression>, 
    ... 
    }
    

    例如:

    modify( LoanApplication ) { 
    setAmount( 100 ), 
    setApproved ( true ) 
    }
    

    update
    他可以更新指定字段和要更新的相关Fact,并将更改通知给Drools引擎。Fact更改后,必须在另一个可能受影响的Fact之前调用update。为了避免此操作,请使用modify。如果定义了属性更改监听器,则不需要进行update操作。

    update ( <object, <handle> ) // Informs the Drools engine that an object has changed  
    update ( <object> ) // Causes `KieSession`  to  search  for a fact handle of the object
    

    例如:

    LoanApplication.setAmount( 100 );
    update( LoanApplication );
    

    insert
    它可以将一个新的Fact插入到working memory中。

    insert( new <object> );
    

    例如:

    insert( new Applicant() );
    

    insertLogical
    使用它可以在逻辑上将一个新的Fact插入到Drools引擎中。Drools引擎负责该Fact的插入和删除。而在通常地插入操作,则需要手动进行删除操作。进行逻辑插入后,如果规则条件不再满足,则该Fact会自动删除。

    insertLogical( new <object> );
    

    例如:

    insertLogical( new Applicant() );
    

    delete
    使用它可以从Drools引擎删除对象。和关键字retract具有相同的效果。

    delete( <object> );
    

    例如:

    delete( Applicant );
    

    1.9.2 来自droolskcontext 变量支持的动作
    Drools还支持了一些额外的操作方法,可以在RHS中使用他们。drools变量调用来自KnowledgeHelper类的方法。
    例如:

    rule "Using drools variable"
    when 
      //
    then
      drools.halt();
      kcontext.getKieRuntime().halt()
    end
    

    1.9.3 附加条件和命名结果的高级规则操作
    若每个规则,具有一些相同的条件,为了消除冗长且重复的条件,可以使用下列示例。例如:

    rule "Give 10% discount to customers older than 60"  	when 
    	$customer : Customer( age > 60 ) 
    	then 
    	modify($customer) { setDiscount( 0.1 ) }; 
    	end 
    rule "Give free parking to customers older than 60"  			 
      	when 
    	$customer : Customer( age > 60 ) 
    	$car : Car( owner == $customer )
    	then modify($car) { setFreeParking( true ) }; 
    end
    

    具有相同的条件我们可以继承其规则,例如:

    rule "Give 10% discount to customers older than 60"  
    	when 
    	$customer : Customer( age > 60 ) 
    	then 
    	modify($customer) { setDiscount( 0.1 ) }; 
    	end 
    
    rule "Give free parking to customers older than 60" 
    extends "Give 10% discount to customers older than 60"  
    	when 
    	$car : Car( owner == $customer ) 
    	then modify($car) { setFreeParking( true ) }; 
    	end
    

    还可以使用规则合并并标记不同规则执行的单个操作,如下:

    rule "Give 10% discount and free parking to customers older than 60"  
    	when 
    		$customer : Customer( age > 60 ) do[giveDiscount] 
    		$car : Car( owner == $customer ) 
    	then 
    		modify($car) { setFreeParking( true ) }; 
    	then[giveDiscount] 
    		modify($customer) { setDiscount( 0.1 ) }; 
    end
    
    

    上述示例包含了2个规则的操作,一个默认和名为giveDiscount的操作。当客户年龄到达69岁后,在关键字do的条件下激活giveDiscount操作,不管后面约束是否通过。如果客户还拥有Car,则还会激活免费停车的操作。默认操作总是在已命名结果后执行。
    此外,还可以对命名结果的激活设置额外的条件,例如使用if-elseif-else if语句。if语句中的条件始终根据其紧前面的模式匹配。例如:

    rule "Give free parking to customers older than 60 and 10% discount to golden ones among them"  
    	when 
    		$customer : Customer( age > 60 ) 
    		if ( type == "Golden" ) do[giveDiscount] 
    		$car : Car( owner == $customer ) 
    	then 
    		modify($car) { setFreeParking( true ) }; 
    	then[giveDiscount] 
    		modify($customer) { setDiscount( 0.1 ) }; 
    end
    
    rule "Give free parking and 10% discount to over 60 Golden customer and 5% to Silver ones" 
    	when 
    		$customer : Customer( age > 60 ) 
    		if ( type == "Golden" ) do[giveDiscount10] 
    		else  if ( type == "Silver" ) break[giveDiscount5] 
    		$car : Car( owner == $customer ) 
    	then 
    		modify($car) { setFreeParking( true ) }; 
    	then[giveDiscount10] 
    		modify($customer) { setDiscount( 0.1 ) }; 
    	then[giveDiscount5] 
    		modify($customer) { setDiscount( 0.05 ) }; 
    end
    

    上述规则表明了客户60岁以上,若是Golden客户,激活名为giveDiscount10的操作;若是Silver客户,则激活名为giveDiscount5的操作,该规则使用了break关键字,阻止了规则的进一步的条件评估。但如果命名结果不符合do的任何条件,而break被激活,则该条规则无法编译,因为从未达到规则的条件部分。

    生活虽不能自由,但愿心能自由。
    评论