1. 程式人生 > >《Drools7.0.0.Final規則引擎教程》第4章 4.4 約束(Pattern的一部分)

《Drools7.0.0.Final規則引擎教程》第4章 4.4 約束(Pattern的一部分)

4.4.3 約束(Pattern的一部分)

前面我們已經介紹了條件約束在Pattern中位置了,那麼什麼是條件約束呢?簡單來說就是一個返回true或者false的表示式,比如下面的5小於6,就是一個約束條件。

Person( 5 < 6 )

從本質上來講,它是JAVA表示式的一種增強版本(比如屬性訪問),同時它又有一些小的區別,比如equals方法和==的語言區別。下面我們就深入瞭解一下。

訪問JavaBean中的屬性

任何一個JavaBean中的屬性都可以訪問,不過對應的屬性要提供getter方法或isProperty方法。比如:

Person( age == 50 )

// 與上面擁有同樣的效果
Person( getAge() == 50 )

Drools使用java標準的類檢查,因此遵循java標準即可。同時,巢狀屬性也是支援的,比如:

Person( address.houseNumber == 50 )

// 與上面寫法相同
Person( getAddress().getHouseNumber() == 50 )

在使用有狀態session的情況下使用巢狀屬性需要注意屬性的值可能被其他地方修改。要麼認為它們是不可變的,當任何一個父引用被插入到working memory中。或者,如果要修改巢狀屬性值,則應將所有外部fact標記更新。在上面的例子中,當houseNumber屬性值改變時,任何一個包含Address的Person需要被標記更新。

Java表示式

在pattern的約束條件中,可以任何返回結果為布林型別的java表示式。當然,java表示式也可以和增強的表示式進行結合使用,比如屬性訪問。可以通過使用括號來更改計算優先順序,如在任一邏輯或數學表示式中。

Person( age > 100 && ( age % 10 == 0 ) )

也可以直接使用java提供的工具方法來進行操作計算:

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

在使用的過程中需要注意,在LHS中執行的方法只能是隻讀的,不能在執行方法過程中改變改變FACT物件的值,否則會影響規則的正確執行。

Person( incrementAndGetAge() == 10 ) //不要像這樣在比較的過程中更新Fact物件

另外,FACT物件的相關狀態除了被在working memory中進行更新操作,不應該每次呼叫時狀態會發生變化。

Person( System.currentTimeMillis() % 1000 == 0 ) // 不要這樣實現

標準Java運算子優先順序也適用,請參見下面的運算子優先順序列表。所有的操作符都有標準的Java語義,除了==和!=。它們的null安全的,就相當於java中比較兩個字串時把常量字串放前面呼叫equals方法的效果一樣。

約束條件的比較過程中是會進行強制型別轉換的,比如在資料計算中傳入字串“10”,則能成功轉換成數字10進行計算。但如果,此時傳入的值無法進行轉換,比如傳了“ten”,那麼將會丟擲異常。

逗號分隔符

逗號可以對約束條件進行分組,它的作用相當於“AND”。

// Person的年齡要超過50,並且重量 超過80 kg
Person( age > 50, weight > 80 )

雖然“&&”和“,”擁有相同的功能,但是它們有不同的優先順序。“&&”優先於“||”,“&&”和“||”又優先於“,”。但建議優先使用“,”分隔符,因為它更利於閱讀理解和引擎的優化操作。同時,逗號分隔符不能和其他操作符混合使用,比如:

Person( ( age > 50, weight > 80 ) || height > 2 ) // 會編譯錯誤

// 使用此種方法替代
Person( ( age > 50 && weight > 80 ) || height > 2 )

繫結變數

一個屬性可以繫結到一個變數:

// 2 person的age屬性值相同
Person( $firstAge : age ) // 繫結
Person( age == $firstAge ) // 約束表示式

字首$只是個通用慣例,在複雜規則中可以通過它來區分變數和屬性。為了向後相容,允許(但不推薦)混合使用約束繫結和約束表示式。

// 不建議這樣寫
Person( $age : age * 2 < 100 )

// 推薦(分離繫結和約束表示式)
Person( age * 2 < 100, $age : age )

使用操作符“==”來繫結變數,Drools會使用雜湊索引來提高執行效能。

內部類分組訪問

通常情況,我們訪問一個內部類的多個屬性時會有如下的寫法:

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

Drools提供的分組訪問可以更加方便進行使用:

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

注意字首’.’是用來區分巢狀物件約束和方法呼叫所必需的。

內部強制轉換

在使用內部類的時候,往往需要將其轉換為父類,在規則中可以通過“#”來進行強制轉換:

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

上面的例子將Address強制轉換為LongAddress.,這樣使得getter方法變得可用。如果無法強制轉換,表示式計算的結果為false。強制轉換也支援全路徑的寫法:

Person( name == "mark", address#org.domain.LongAddress.country == "uk" )

多次內部轉換語法:

Person( name == "mark", address#LongAddress.country#DetailedCountry.population > 10000000 )

也可以使用instanceof操作符進行判斷,判斷之後將進一步使用該屬性進行比較。

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

日期字元

規則語法中除了支援JAVA標準字元,同時也支援日期字元。Drools預設支援的日期格式為“dd-mmm-yyyy”,可以通過設定系統變數“drools.dateformat”的值來改變預設的日期格式。

Cheese( bestBefore < "27-Oct-2009" )

List和Map的訪問

訪問List:

// 和childList(0).getAge() == 18效果相同
Person( childList[0].age == 18 )

根據key訪問map:

// 和credentialMap.get("jsmith").isValid()相同
Person( credentialMap["jsmith"].valid )

&&和||

約束表示式可以通過&&和||來進行判斷比較,此處用法與標準Java相似,當組合使用時,可通過括號來劃分優先順序。

Person( age > 30 && < 40 )
Person( age ( (> 30 && < 40) ||(> 20 && < 25) ) )
Person( age > 30 && < 40 || location == "london" )

DRL特殊操作符

“< ⇐ > >=”操作符用於屬性的比較是按照預設的排序,比如日期屬性使用小於號標示可以按照日期排序,當使用在String字串的比較時,則按照字母順序進行排序。此操作符僅適用於可比較的屬性。

Person( firstName < $otherFirstName )
Person( birthDate < $otherBirthDate )

“!.”提供了一個預設空校驗的操作。當使用此操作符時,會先校驗當前物件是否為null,如果不為null再呼叫其方法或獲得其屬性進行判斷。一旦當前操作物件為null,則相當於結果為false。

Person( $streetName : address!.street )

// 上面的寫法相當於
Person( address != null, $streetName : address.street )

matches操作符可使用Java的正則表示式進行字串的匹配,通常情況下是對字串進行匹配,但也支援變數值為正確的表示式的方式。此操作符僅適用於字串屬性。如果屬性值為null,匹配的結果始終為false。

Cheese( type matches "(Buffalo)?\\S*Mozzarella" )

not matches方法與matches相同,唯一不同的是返回的結果與之相反。

Cheese( type not matches "(Buffalo)?\\S*Mozzarella" )

contains操作符判斷一個集合屬性或元素是否包含指定字串或變數值。僅適用於集合屬性。也可以用於替代String.contains()來檢查約束條件。not contains用法與之相同,結果取反。

CheeseCounter( cheeses contains "stilton" ) // 包含字串
CheeseCounter( cheeses contains $var ) // 包含變數

Cheese( name contains "tilto" )
Person( fullName contains "Jr" )
String( this contains "foo" )

memberOf用來檢查屬性值是否為集合,此集合的表示必須為變數。not memberOf使用方法相同,結果取反。

CheeseCounter( cheese memberOf $matureCheeses )

soundslike的效果與matches相似,但它用來檢查一個字串的發音是否與指定的字元十分相似(使用英語發音)。

// 匹配 "fubar""foobar"
Cheese( name soundslike 'foobar' )

str操作用來比較一個字串是否以指定字串開頭或結尾,有可以用於比較字串的長度。

Message( routingValue str[startsWith] "R1" )

Message( routingValue str[endsWith] "R2" )

Message( routingValue str[length] 17 )

in和notin用來匹配一組資料中是否含一個或多個匹配的字串,使用的方法與資料庫中in的使用方法相似。待匹配的資料可以是字串、變數。

Person( $cheese : favouriteCheese )
Cheese( type in ( "stilton", "cheddar", $cheese ) )

運算子優先順序

操作型別 操作符 備註
(巢狀/空安全)屬性訪問 .!. 非標準java語義
List/Map訪問 [ ] 非標準java語義
約束繫結 : 非標準java語義
乘除 */%
加減 +-
移位 <<>>>>>
關係 <>⇐>=instanceof
==!= 未使用標準java語義,某些語義相當於equals。
非短路AND &
非短路異或 ^
非短路包含OR |
邏輯與 &&
邏輯或 ||
三元運算子 ? :
逗號分隔,相當於and , 非標準java語義

後語

此係列課程持續更新中,QQ群:593177274(可掃描左上側欄目二維碼),歡迎大家加入討論。點選連結關注《Drools部落格專欄》。由於Drools資料較少,教程編寫不易,每篇部落格都親身實踐編寫demo。如果對你有幫助也歡迎讚賞(微信)! 也是對原創的最大支援!
這裡寫圖片描述

相關推薦

Drools7.0.0.Final規則引擎教程1 Drools簡介

1.1 什麼是規則引擎 規則引擎是由推理引擎發展而來,是一種嵌入在應用程式中的元件,實現了將業務決策從應用程式程式碼中分離出來,並使用預定義的語義模組編寫業務決策。接受資料輸入,解釋業務規則,並根據業務規則做出業務決策。 大多數規則引擎都支援規則的次序和規

Drools7.0.0.Final規則引擎教程4 4.6 結果條件

結果條件 在Java中,如果有重複的程式碼我們會考慮進行重構,抽取公共方法或繼承父類,以減少相同的程式碼在多處出現,達到程式碼的最優管理和不必要的麻煩。Drools同樣提供了類似的功能。下面我們以例項來逐步說明。 像下面最原始的兩條規則,有相同的業務判斷,也

Drools7.0.0.Final規則引擎教程3 3.2 KIE API解析

3.2.4 KieServices 該介面提供了很多方法,可以通過這些方法訪問KIE關於構建和執行的相關物件,比如說可以獲取KieContainer,利用KieContainer來訪問KBase和KSession等資訊;可以獲取KieRepository物件

Drools7.0.0.Final規則引擎教程4 4.4 約束Pattern一部分

4.4.3 約束(Pattern的一部分) 前面我們已經介紹了條件約束在Pattern中位置了,那麼什麼是條件約束呢?簡單來說就是一個返回true或者false的表示式,比如下面的5小於6,就是一個約束條件。 Person( 5 < 6 ) 從本質上

Drools7.0.0.Final規則引擎教程4 註釋&錯誤資訊

註釋 像Java開發語言一樣,Drools檔案中也可以添加註釋。註釋部分Drools引擎是會將其忽略調的。單行註釋使用“//”,示例如下: rule "Testing Comments" when // this is a single line

Drools7.0.0.Final規則引擎教程》之Springboot整合

本來準備按部就班的一章一章更新Drools相關教程,怎奈QQ群組(593177274)有朋友急需Springboot與Drools的整合demo,於是抽出時間寫了一個,現在拿出來分享一下。加入群組可免費下載demo,也可以在CSDN下載頻道下載:Springbo

Drools7.0.0.Final規則引擎教程》番外例項篇——Map使用案例

背景 技術交流群中,不少朋友在問,如何在Drools規則檔案中使用Map。今天就用例項帶大家瞭解一下map的使用方法。 例項程式碼 測試部分程式碼: @Test public void testMapUsage() { KieSe

AutoCAD2012從入門到精通中文視訊教程 19課 修剪與延伸個人收藏

修剪和延伸的基本技巧首先是選擇,首先要選擇修剪、延伸邊界,或稱為切割物件,也就是選擇作為修剪和延伸的基準的物件,然後就是選擇要被修剪或延伸的物件,掌握了這兩者的選擇技巧就基本掌握了修剪和延伸的操作。 CAD修剪(Trim)和延伸(Extend)的使用技巧 2

Hadoop基礎教程-2 Hadoop快速入門2.2 Hadoop下載與安裝

2.1 Hadoop下載與安裝2.1.1 官網下載可以使用迅雷或QQ旋風等多執行緒下載工具來下載,支援斷點續傳。成功下載後得到hadoop-2.7.3.tar.gz壓縮檔案,204M。請檢查壓縮包是否204M,瀏覽器下載的話可能會中斷。2.1.2 上傳至虛擬機器通過ll或ls命令可以檢視到已經上傳到虛擬機器n

Hadoop基礎教程-1 環境安裝配置1.5 構建叢集

第1章 環境安裝配置 1.5 構建叢集 1、叢集概念 根據百度的解釋: 叢集是一組相互獨立的、通過高速網路互聯的計算機,它們構成了一個組,並以單一系統的模式加以管理。一個客戶與叢集相互作用時,叢集像是一個獨立的伺服器。叢集配置是用於提高可用性和可

Node.js進階教程七步:koa框架koa1,koa2-何韜-專題視訊課程

Node.js進階教程第七步:koa框架(koa1,koa2)—6512人已學習 課程介紹        koa 致力於成為一個更小、更富有表現力、更健壯的 Web 框架。Koa 應用是一個包含一系列中介軟體 generator 函式的物件。Koa提供了一個輕量優雅的函式庫,

Hadoop基礎教程-2 Hadoop快速入門2.4 Hadoop單機執行

第2章 Hadoop快速入門2.4 Hadoop單機執行緊接上一節內容,首先切換到Hadoop根目錄 或者cd /opt/hadoop-2.7.3進入Hadoop根目錄 通過pwd命令可以知道當前所在目錄[root@node1 hadoop-2.7.3]# pwd注意:本節命令都將在/opt/hadoop-2

【閱讀筆記】《C程序員 從校園到職場》 程序的樣式大括號

突出 char s 結構體 需要 初始化 detail 處理 思維 https 參考: https://blog.csdn.net/zhouzhaoxiong1227/article/details/22820533 一、.初始化數組變量 在實際的軟件開

:隨機化續1

限制 調試 each 範圍 實例 func 文件中 約束 hand 6.6 pre_randomize和post_randomize函數 我們在調用randomize()函數之前或者之後要立即執行一些操作。比如,在隨機化之前可能要設置類裏的一些非隨機變量(上下限、權重),或

:隨機化續2

重要 之間 ilog -o bbbb 動態 調試 即使 不同 6.10 隨機化句柄數組 如果想要產生多個隨機對象,那麽你可能需要建立隨機句柄數組,和整數數組不同,隨機求解器不會創建對象,所以你需要在隨機化前分配所有的元素。 動態數組可以按照需要分配最大數量的元素,然後按照約

組合語言暫存器記憶體訪問

3.1  在CPU中,用一個16位暫存器來儲存一個字,一個字兩個位元組,高8位存放高位位元組,低8位存放低位位元組,低位元組所在的記憶體單元稱為起始地址。 3.2 3.3 8086CPU中,通常用DS暫存器來存放要訪問資料的段地址(字或者位元組) 舉個例子: mov bx,1000H mov

3 暫存器記憶體訪問小結

記憶體中字的儲存 字單元,即存放一個字形資料(16位)的記憶體單元,由兩個地址連續的記憶體單元組成。高地址記憶體單元中存放字型資料的高位位元組,低地址記憶體單元中存放字型資料的低位位元組。我們將起始地址為N的字單元簡稱為N地址字單元。   DS和[address] “[...]”表示一個記憶

暫存器記憶體訪問相關內容總結

      在本章中,我們從訪問記憶體的角度繼續學習了幾個暫存器。我們提出字單元的概念:字單元,即存放一個字型資料(16位)的記憶體單元,由兩個地址連續的記憶體單元組成。高地址記憶體單元中存放字型資料的高位位元組,低地址記憶體單元中存放字型資料的低位位元組。CPU要讀寫一個記憶體

強化學習RLAI讀書筆記差分學習TD-learning

第六章:Temporal-Difference Learning TD-learning演算法是強化學習中一個獨具特色而又核心的想法,結合了蒙特卡洛演算法和動態規劃的想法。和MC一樣不需要環境模型直接從sample裡學習,也像DP一樣使用bootstrap通過別的狀態值的估計更新當前狀態值。首先

《機器學習》 周志華學習筆記 支援向量機課後習題python 實現

一、 1.間隔與支援向量 2.對偶問題 3.核函式 xi與xj在特徵空間的內積等於他們在原始yangben空間中通過函式k(.,.)計算的結果。 核矩陣K總是半正定的。 4.軟間隔與正則化 軟間隔允許某些samples不滿足約束  鬆弛變數 5.支援