<!--[if !supportLists]--> 1åQ?span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal"> <!--[endif]--> 概述åQ?/span>
<!--[if !supportLists]--> 1.1   <!--[endif]--> 规则文äšg
一个规则文仉™€šå¸¸æ˜¯ä¸€ä¸ªä»¥
.drl
扩展å结ž®„¡š„æ–‡äšg。在一ä¸?/span>
drl
æ–‡äšgä¸ï¼Œä½ å¯ä»¥æœ‰å¤šæ¡
rules
åQ?/span>
functions
½{‰ç‰ã€‚å°½½Ž¡å¦‚æ¤ï¼Œä½ 也å¯ä»¥ž®†ä½ 的规则分布在多个文äšgä¸ï¼Œ˜q™æœ‰åˆ©äºŽ½Ž¡ç†å¤§é‡çš„规则。一ä¸?/span>
DRL
æ–‡äšg是一个简å•的文本文äšgã€?/span>
1.2
规则的结�/span>
一个规则结构大致如下:(x¨¬)
å¯ä»¥çœ‹åˆ°åQŒè¿™æ˜¯éžå¸¸ç®€å•çš„ã€‚é€šå¸¸çš„æ ‡ç‚¹ç¬¦å·éƒ½æ˜¯ä¸éœ€è¦çš„åQŒç”šè‡Œ™¿žâ€?/span> name â€çš„åŒå¼•å·éƒ½æ˜¯ä¸éœ€è¦çš„ã€?/span> ATTRIBUTES 是简å•çš„åQŒä¹Ÿæ˜¯å¯é€‰çš„åQŒæ¥æç¤ºè§„则的行为方å¼ã€?/span> LHS 是规则的æ¡äšg部分åQŒéœ€è¦æŒ‰ç…§ä¸€å®šçš„è¯æ³•æ¥å†™ã€?/span> RHS 基本上是一个å…许执è¡?/span> Java è¯æ³•的代ç çš„å—(以厞®†ä¼š(x¨¬)æ”¯æŒ groovy å’?/span> C åQƒï¼‰(j¨ª)。ä“Q何在 LHS ä¸ä‹É用的å˜é‡éƒ½å¯ä»¥åœ¨ RHS ä¸ä‹É用ã€?/span>
注æ„åQšæ¯è¡Œå¼€å§‹çš„½Iºæ ¼æ˜¯ä¸é‡è¦çš„,除éžåœ?/span> DSL åQ?/span> Domain Specific Language åQ‰è¯a€ä¸æœ‰ç‰¹åˆ«çš„æŒ‡æ˜Žã€?/span>
<!--[if !supportLists]--> 1.3Â Â <!--[endif]--> Domain Specific Language
Domain Specific Language 是对原生规则è¯è¨€çš„åŠ å¼ºã€‚å®ƒä»¬ä‹É用â€?/span> expander â€æœºåˆ¶ã€?/span> Expander 机制是一¿U坿‰©å±•çš?/span> API ã€‚ä½ å¯ä»¥ä½¿ç”¨ .dsl æ–‡äšgåQŒæ¥æä¾›ä»ŽåŸŸæˆ–自然è¯a€åˆ°è§„则è¯a€å’Œä½ çš„åŸŸå¯¹è±¡çš„æ˜ ž®„ã€‚ä½ å¯ä»¥ž®?/span> .dsl æ–‡äšgçœ‹æˆæ˜¯å¯¹ä½ çš„åŸŸæ¨¡åž‹çš„æ˜ å°„ã€?/span> DSL æä¾›äº?ji¨£n)更高的规则å¯è¯»æ€§ï¼Œä½ å¯ä»¥é€‰æ‹©ä½¿ç”¨ä½ 自己创建的 DSL åQŒæˆ–者是原生的规则è¯a€ã€?/span>
1.4
ä¿ç•™å?/span>
<!--[if !supportLists]--> 2.  <!--[endif]--> 注释
Figure 2.1. Single line comment
<!--[if !supportLists]-->
3. Â Â Â
<!--[endif]--> Package
一个包�/span>
rule
和其他相关结构,�/span>
import
å’?/span>
global
的集åˆã€?/span>
Package
çš„æˆå‘˜ä¹‹é—´é€šå¸¸éƒ½æ˜¯ç›¸å…³è”的。一ä¸?/span>
Package
代表äº?ji¨£n)一个命å空é—ß_(d¨¢)¼ˆ
namespace
åQ‰ï¼Œç”¨æ¥ä½¿ç»™å®šçš„规则¾l„ä¹‹é—´ä¿æŒå”¯ä¸€æ€§ã€?/span>
Package
çš„åå—æœ¬íw«å°±æ˜¯å‘½å空é—ß_(d¨¢)¼Œòq¶ä¸”与文件或文äšgå¤¹åÆˆæ— å…³è”ã€?/span>
<!--[if !supportEmptyParas]-->
å¯ä»¥ž®†æ¥è‡ªä¸åŒè§„则æºçš„规则装é…åœ¨ä¸€èµøP¼Œå‰ææ˜¯è¿™äº›è§„则必™åÕd¤„在åŒä¸€ä¸ªå‘½å空间ä¸ã€‚å°½½Ž¡å¦‚æ¤ï¼Œä¸€ä¸ªé€šå¸¸çš„结构是ž®†å¤„于åŒä¸€ä¸ªå‘½å空间ä¸çš„æ‰€æœ‰è§„则都攑֜¨åŒä¸€ä¸ªç›¸åŒçš„æ–‡äšgä¸ã€?/span>
下é¢çš?/span>
rail-road
图显½CÞZº†(ji¨£n)¾l„æˆä¸€ä¸?/span>
Package
的所有组件。注æ„:(x¨¬)一ä¸?/span>
package
必须有一个命å空é—ß_(d¨¢)¼Œòq¶ä¸”采用
Java
包å的约定。在一个规则文件ä¸åQŒå„¾l„äšg出现的佾|®æ˜¯ä»ÀL„的,除了(ji¨£n)â€?/span>
package
â€å’Œâ€?/span>
expander
â€è¯å¥å¿…™åÕd‡ºçŽ°åœ¨ä»ÖM½•一个规则之å‰ï¼Œæ”‘Öœ¨æ–‡äšg的顶部。在ä»ÖM½•情况下,分å·éƒ½æ˜¯å¯é€‰çš„ã€?/span>
Import è¯å¥çš„ä‹É用很åƒ?/span> Java ä¸çš„ import è¯å¥ã€‚ä½ éœ€è¦äØ“(f¨´)ä½ è¦åœ¨è§„则ä¸ä½¿ç”¨çš„对象,指定完整的èµ\径和¾cÕdã€?/span> Drools 自动从相åŒå‘½åçš„ java 包ä¸å¼•入所需的类ã€?/span>
3.2 expander
Figure 3.3. expander
expander è¯å¥æ˜¯å¯é€‰çš„åQŒæ˜¯ç”¨æ¥æŒ‡å®š Domain Specific Language 的酾|®ï¼ˆé€šå¸¸æ˜¯ä¸€ä¸?/span> .dsl æ–‡äšgåQ‰ã€‚这使得解æžå™¨å¯ä»¥ç†è§£ç”¨ä½ 自å·Þqš„ DSL è¯è¨€æ‰€å†™çš„规则ã€?/span>
3.3 globalGlobal ž®±æ˜¯å…¨å±€å˜é‡ã€‚如果多ä¸?/span> package 声明äº?ji¨£n)å…·æœ‰ç›¸åŒæ ‡è¯†ç¬¦ç?/span> global åQŒé‚£ä¹ˆå®ƒä»¬å¿…需是相åŒçš„¾cÕdž‹åQŒåƈ且所有的引用都是相åŒçš„。它们通常用楘q”回数æ®åQŒæ¯”å¦?/span> actions çš„æ—¥å¿—ï¼Œæˆ–è€…äØ“(f¨´) rules æä¾›æ‰€éœ€çš„æ•°æ®æˆ–æœåŠ¡ã€?/span> global òq¶ä¸æ˜¯é€šè¿‡ assert 动作攑օ¥ WorkingMemory 的,所有当 global å‘ç”Ÿæ”¹å˜æ—Óž¼Œå¼•擎ž®†ä¸ä¼?x¨¬)知é“。所以, global ä¸èƒ½ä½œäØ“(f¨´)¾U¦æŸæ¡äšgåQŒé™¤éžå®ƒä»¬çš„值是 final 的。将 global 错误的ä‹É用在¾U¦æŸæ¡äšgä¸ï¼Œä¼?x¨¬)äñ”生ä×o(h¨´)人惊讶的错误¾l“æžœã€?/span>
<!--[if !supportEmptyParas]-->
注æ„åQ?/span>
global
åªæ˜¯ä»Žä½ çš?/span>
application
ä¸ä¼ å…?/span>
WorkingMemory
的对象的命å实例。这æ„味ç€ä½ å¯ä»¥ä¼ å…¥ä“Qä½•ä½ æƒŒ™¦çš„å¯¹è±¡ã€‚ä½ å¯ä»¥ä¼ 入一ä¸?/span>
service locator
åQŒæˆ–者是一ä¸?/span>
service
本èínã€?/span>
<!--[if !supportEmptyParas]-->
下é¢çš„例åä¸åQŒæœ‰ä¸€ä¸?/span>
EmailService
çš„å®žä¾‹ã€‚åœ¨ä½ è°ƒç”¨è§„åˆ™å¼•æ“Žçš„ä»£ç ä¸ï¼Œä½ 有一ä¸?/span>
EmailService
对象åQŒç„¶åŽæŠŠå®ƒæ”¾å…?/span>
WorkingMemory
。在
DRL
æ–‡äšgä¸ï¼Œä½ 声明了(ji¨£n)ä¸€ä¸ªç±»åž‹äØ“(f¨´)
EmailService
çš?/span>
global
åQŒç„¶åŽå°†å®ƒå‘½å䨓(f¨´)â€?/span>
email
â€ï¼Œåƒè¿™æ øP¼š(x¨¬)
global EmailService email
åQ›ã€‚ç„¶åŽåœ¨ä½ 的规则çš?/span>
RHS
ä¸ï¼Œä½ å¯ä»¥ä‹É用它åQŒåƒ˜q™æ ·åQ?/span>
email.sendSMS(number,message)
½{‰ç‰ã€?/span>
4. Function
Function æ˜¯å°†ä»£ç æ”‘Öˆ°ä½ 的规则æºä¸çš„一¿U方法。它们åªèƒ½åš¾cÖM¼¼ Helper ¾cÕdšçš„事åQˆå®žé™…上¾~–译器在背åŽå¸®ä½ 生æˆäº?/span> Helper ¾c»ï¼‰(j¨ª)。在一ä¸?/span> rule ä¸ä‹Éç”?/span> function 的主è¦ä¼˜åŠ¿æ˜¯åQŒä½ å¯ä»¥ä¿æŒæ‰€æœ‰çš„逻辑都在一个地方,òq¶ä¸”ä½ å¯ä»¥æ ¹æ®éœ€è¦æ¥æ”¹å˜ function åQˆè¿™å¯èƒ½æ˜¯å¥½äº‹ä¹Ÿå¯èƒ½æ˜¯å事)(j¨ª)ã€?/span> Function 最有用的就是在规则çš?/span> RHS 调用 actions åQŒç‰¹åˆ«æ˜¯å½“é‚£ä¸?/span> action 需è¦åå¤è°ƒç”¨çš„æ—¶å€™ã€?/span>
<!--[if !supportEmptyParas]-->
一个典型的 function 声明如下åQ?/span>
<!--[if !supportEmptyParas]-->
注æ„åQšâ€?/span>
function
â€å…³é”®å—çš„ä‹Éç”¨ï¼Œå®ƒåÆˆä¸çœŸæ£æ˜¯
Java
的一部分。�/span>
function
çš„å‚æ•°å°±åƒæ˜¯ä¸€ä¸ªæ™®é€šçš„
method
åQˆå¦‚æžœä¸éœ€è¦å‚æ•°å°±ä¸ç”¨å†™ï¼‰(j¨ª)。返回类型也跟普通的
method
ä¸€æ —÷€‚在一æ¡è§„则(在它çš?/span>
RHS
ä¸ï¼Œæˆ–å¯èƒ½æ˜¯ä¸€ä¸?/span>
eval
åQ‰ä¸è°ƒç”¨
function
åQŒå°±åƒè°ƒç”¨ä¸€ä¸?/span>
method
ä¸€æ øP¼Œåªéœ€è¦?/span>
function
çš„åå—,òq¶ä¼ ¾l™å®ƒå‚æ•°ã€?/span>
<!--[if !supportEmptyParas]-->
function
的替代å“åQŒå¯ä»¥ä‹É用一ä¸?/span>
Helper
¾cÖM¸çš„é™(r¨´n)æ€æ–¹æ³•:(x¨¬)
Foo.doSomething()
åQŒæˆ–者以
global
的方å¼ä¼ 入一ä¸?/span>
Helper
¾cÀLˆ–æœåŠ¡çš„å®žä¾‹ï¼š(x¨¬)
foo.doSomething()
åQ?/span>
foo
是一个命åçš„
global
å˜é‡åQ‰ã€?/span>
<!--[if !supportEmptyParas]-->
http://labs.jboss.com/portal/index.html?ctrl:id=page.default.downloads&project=jbossrules
ä¸‹è²æ–‡äšg说明åQ?/span>
JBoss Rules 3.0.1 Binaries (includes javadocs) åQ?/span> 13MB åQ‰â€?/span> ä»…ä»…åŒ…å« JBoss Rules çš„å››ä¸ªæ ¸å¿?j¨©)类库ï¼?x¨¬)
<!--[if !supportLists]--> l        <!--[endif]--> drools-core.jaråQ?/span>æ ¸å¿ƒ(j¨©)引擎åQŒè¿è¡Œæ—¶¾l„äšg。包å«äº†(ji¨£n)RETE引擎å’?/span>LEAPS引擎åQ?/span>
<!--[if !supportLists]--> l        <!--[endif]--> drools-compiler.jaråQ?/span>规则文äšg的编译组ä»Óž¼Œæž„å¾å¯æ‰§è¡Œçš„RuleBaseåQ?/span>
<!--[if !supportLists]--> l        <!--[endif]--> drools-jsr94.jaråQ?/span>æä¾›äº?/span>JSR-94的兼容实玎ͼŒæœ¬è´¨ä¸Šæ˜¯drools- compiler¾l„äšg的包裹层。注æ„:(x¨¬)ç”׃ºŽJSR94规约的é™åˆÓž¼Œä¸æ˜¯æ‰€æœ‰çš„特点都å¯ä»¥é€šè¿‡æ¤æŽ¥å£æš´éœŒÓ€?/span>
<!--[if !supportLists]--> l        <!--[endif]--> drools-decisiontables.jaråQ?/span>决ç–表的“编译â€ç»„ä»Óž¼ˆä½¿ç”¨äº?/span>drools- compiler¾l„äšgåQ‰ã€‚支æŒ?/span>excelå’?/span>CSVè¾“å…¥æ ¼å¼ã€?/span>
JBoss Rules 3.0.1 Binaries with dependencies (includes javadocs) åQ?/span> 23 MB åQ‰ï¼ 包å«äº?/span> JBoss Rules çš„æ ¸å¿?j¨©)类库和它们ç?/span> dependencies åQ?/span>
<!--[if !supportLists]--> l        <!--[endif]--> antlr-2.7.6.jar
<!--[if !supportLists]--> l        <!--[endif]--> antlr-3.0ea8.jar
<!--[if !supportLists]--> l        <!--[endif]--> colt-1.2.0.jar
<!--[if !supportLists]--> l        <!--[endif]--> commons-collections-3.1.jar
<!--[if !supportLists]--> l        <!--[endif]--> commons-io-1.1.jar
<!--[if !supportLists]--> l        <!--[endif]--> commons-jci-core-1.0-406301.jar
<!--[if !supportLists]--> l        <!--[endif]--> commons-jci-eclipse-3.2.0.666.jar
<!--[if !supportLists]--> l        <!--[endif]--> commons-jci-janino-2.4.3.jar
<!--[if !supportLists]--> l        <!--[endif]--> commons-lang-2.1.jar
<!--[if !supportLists]--> l        <!--[endif]--> commons-logging-api-1.0.4.jar
<!--[if !supportLists]--> l        <!--[endif]--> concurrent-1.3.4.jar
<!--[if !supportLists]--> l        <!--[endif]--> core-3.2.0.666.jar
<!--[if !supportLists]--> l        <!--[endif]--> janino-2.4.3.jar
<!--[if !supportLists]--> l        <!--[endif]--> jsr94-1.1.jar
<!--[if !supportLists]--> l        <!--[endif]--> jung-1.7.2.jar
<!--[if !supportLists]--> l        <!--[endif]--> junit-3.8.1.jar
<!--[if !supportLists]--> l        <!--[endif]--> poi-2.5.1-final-20040804.jar
<!--[if !supportLists]--> l        <!--[endif]--> stringtemplate-2.3b6.jar
<!--[if !supportLists]--> l        <!--[endif]--> xercesImpl-2.6.2.jar
<!--[if !supportLists]--> l        <!--[endif]--> xml-apis-1.0.b2.jar
<!--[if !supportLists]--> l        <!--[endif]--> xpp3-1.1.3.4.0.jar
<!--[if !supportLists]--> l        <!--[endif]--> xstream-1.1.3.jar
å¦‚æžœä½ è¿è¡Œåœ¨ Java 1.5 环境下,有一些类库,例如 XML libraries åQŒå¯ä»¥ä¸éœ€è¦ã€‚éœ€è¦æ³¨æ„çš„¾cÕdº“有:(x¨¬)
�/span>
JCI
â€ï¼˜q™æ˜¯
Apache Java Compiler Interface ,
æä¾›äº?ji¨£n)è¿è¡Œæ—¶¾~–译能力。å¯ä»¥é€šè¿‡
PackageBuilderConfiguration
实例æ¥è®¾å®šé‡‡ç”?/span>
eclipse
�/span>
janino
¾~–译器,默认æ˜?/span>
eclipse
åQ?/span>
â€?/span> POI â€ï¼æä¾›äº?ji¨£n)è§£æ?/span> Excel æ–‡äšg的能力;
â€?/span> antlr â€ï¼æä¾›äº?ji¨£n)è§£æžè§„则è¯a€çš„能力ã€?/span>
JBoss Rules IDE 3.0.1 åQ?/span> 13 MB åQ‰ï¼ ˜q™æ˜¯ JBoss Rules çš?/span> Eclipse æ’äšgåQŒåªæ”¯æŒ Eclipse 3.2 或以上版本。它æä¾›äº?ji¨£n)è¿è?/span> JBoss Rules 的所æœ?/span> dependencies ã€‚ä½ å¯ä»¥åˆ›å¾ä¸€ä¸?/span> Rule Project åQŒå®ƒèƒ½å¤Ÿä¸ÞZ½ ¾~–写规则文äšgæä¾›è‡ªåŠ¨å®Œæˆçš„功能,òq¶ä¸”å®ƒäØ“(f¨´)ä½ æä¾›äº†(ji¨£n) Agenda view åQ?/span> WorkingMemory view åQ?/span> Global Data view åQŒä‹Éä½ å¯ä»¥é€šè¿‡ eclipse 视图很清楚的看到 Agenda åQ?/span> WorkingMemory å’?/span> Global Data 的情å†üc(di¨£n)€?/span>
ä½ è¿˜å¯ä»¥é€šè¿‡ update site æ¥è‡ªåŠ¨å®‰è£…è¿™ä¸ªæ’ä»?/span> ,URL 是:(x¨¬)
http://anonsvn.labs.jboss.com/labs/jbossrules/updates/drools-ide-update/
<!--[if !supportEmptyParas]-->Â <!--[endif]-->
RuleBase 是一个è¿è¡Œæ—¶¾l„äšgåQŒå®ƒåŒ…å«äº?ji¨£n)一个或多个 Package 对象。å¯ä»¥åœ¨ä»ÖM½•时刻ž®†ä¸€ä¸?/span> Package å¯¹è±¡åŠ å…¥æˆ–ç§»å‡?/span> RuleBase 对象。一ä¸?/span> RuleBase 对象å¯ä»¥åœ¨ä“Qæ„æ—¶åˆÕd®žä¾‹åŒ–一个或多个 WorkingMemory 对象åQŒåœ¨å®ƒçš„å†…éƒ¨ä¿æŒå¯¹è¿™äº?/span> WorkingMemory 的弱引用ã€?/span> WorkingMemory ç”׃¸€¾pÕdˆ—å组件组æˆã€‚当应用½E‹åºä¸çš„对象è¢?/span> assert ˜q?/span> WorkingMemory åQŒå¯èƒ½ä¼š(x¨¬)坯D‡´ä¸€ä¸ªæˆ–多个 Activation çš„äñ”生,然åŽç”?/span> Agenda 负责安排˜q™äº› Activation 的执行。下图说明了(ji¨£n)上述˜q‡ç¨‹åQ?/span>
2åQŽæž„建(AuthoringåQ‰ï¼š(x¨¬)
ä¸»è¦æœ‰ä¸‰ä¸ªç±»ç”¨æ¥å®Œæˆæž„徘q‡ç¨‹åQ?/span>DrlParser, XmlParser å’?/span> PackageBuilder。两个解æžå™¨¾cÖM»Žä¼ å…¥çš?/span>Reader实例产生descr AST模型ã€?/span>PackageBuilderæä¾›äº?ji¨£n)简便的APIåQŒä‹Éä½ å¯ä»¥å¿½ç•¥é‚£ä¸¤ä¸ª¾cÈš„å˜åœ¨ã€‚这两个½Ž€å•çš„æ–ÒŽ(gu¨©)³•是:(x¨¬)â€?/span>addPackageFromDrlâ€å’Œâ€?/span>addPackageFromXmlâ€ï¼Œä¸¤ä¸ªéƒ½åªè¦ä¼ 入一ä¸?/span>Readerå®žä¾‹ä½œäØ“(f¨´)傿•°ã€‚下é¢çš„例å说明äº?ji¨£n)如何ä»?/span>classpathä¸çš„xmlå’?/span>drlæ–‡äšg创å¾ä¸€ä¸?/span>Package对象。注æ„:(x¨¬)æ‰€æœ‰ä¼ å…¥åŒä¸€ä¸?/span>PackageBuilder实例的规则æºåQŒéƒ½å¿…须是在相åŒçš?/span>package 命å½Iºé—´åQ?/span>namespaceåQ‰ä¸ã€?/span>
PackageBuilder是å¯ä»¥é…¾|®çš„åQŒä‹Éç”?/span>PackageBuilderConfiguration。通常åQŒä½ å¯ä»¥æŒ‡å®šå¦ä¸€ä¸?/span>parent ClassLoader和用什么编译器åQ?/span>compileråQ‰ï¼Œé»˜è®¤æ˜?/span>Eclipse JDTã€‚ä¸‹é¢æ˜¾½CÞZº†(ji¨£n)如何指定JANINO¾~–译器:(x¨¬)
一ä¸?/span>RuleBase包å«äº?ji¨£n)多个将被ä‹É用的规则包ï¼?/span>packages of rulesåQ‰ã€‚一ä¸?/span>RuleBase是å¯ä»¥åºåˆ—化的,所以它å¯ä»¥è¢«é…¾|®åˆ°JNDI或其他类似的æœåŠ¡ã€‚é€šå¸¸åQŒç¬¬ä¸€‹Æ¡ä‹É用时åQŒä¸€ä¸?/span>RuleBaseè¢«åˆ›å»ºåÆˆ¾~“å˜ã€?/span>RuleBaseç”?/span>RuleBaseFactoryæ¥å®žä¾‹åŒ–åQŒé»˜è®¤è¿”回一ä¸?/span>ReteOO RuleBase。å¯ä»¥ä¼ 入傿•°æ¥æŒ‡å®šé‡‡ç”¨ReteOOæˆ?/span>Leaps。然åŽï¼Œç”?/span>addPackageæ–ÒŽ(gu¨©)³•åŠ å…¥Packageå®žä¾‹ã€‚ä½ å¯ä»¥åŠ å…¥æœ‰ç›¸åŒå‘½å空é—ß_(d¨¢)¼ˆnamespaceåQ‰çš„多个Packageã€?/span>
一ä¸?/span> rulebase instance 是线½E‹å®‰å…¨çš„åQŒæ‰€æœ‰ä½ å¯ä»¥åœ¨ä½ 的应用ä¸åQŒè®©ä¸€ä¸?/span> rulebase instance 在多个线½E‹ä¸å…׃ín。对于一ä¸?/span> rulebase 的最通常的æ“作是产生一个新çš?/span> WorkingMemory ã€?/span>
˜q™ä¸ª rulebase ä¿æŒç€åˆ°å®ƒæ‰€äº§ç”Ÿçš?/span> WorkingMemoryd 的弱引用åQŒæ‰€ä»¥åœ¨é•¿æ—¶é—´è¿è¡Œçš„ WorkingMemory ä¸ï¼Œå¦‚æžœ rules å‘生改å˜åQŒè¿™äº?/span> WorkingMemory å¯ä»¥å³ä‹Éçš„æ ¹æ®æœ€æ–°çš„ rules ˜q›è¡Œæ›´æ–°åQŒè€Œä¸å¿…é‡å?/span> WorkingMemory ã€‚ä½ ä¹Ÿå¯ä»¥æŒ‡å®?/span> RuleBase ä¸å¿…ä¿æŒä¸€ä¸ªå¼±å¼•用åQŒä½†æ˜¯ä½ è¦ä¿è¯?/span> RuleBase ä¸ç”¨æ›´æ–°ã€?/span>
ä»ÖM½•时候, Package å¯ä»¥è¢«åŠ å…¥æˆ–¿U»é™¤åQ›æ‰€æœ‰çš„æ”¹å˜éƒ½ä¼š(x¨¬)è¢«åæ˜ 到现å˜çš?/span> WorkingMemory ä¸ã€‚ä¸è¦å¿˜äº?ji¨£n)è°ƒç?/span> fireAllRules() è®?/span> Activations ‹È€å‘ã€?/span>
è™½ç„¶æœ‰åˆ é™¤ä¸€ä¸ªå•独规则的æ–ÒŽ(gu¨©)³•åQŒä½†æ˜¯å´æ²¡æœ‰åŠ å…¥ä¸€ä¸ªå•独规则的æ–ÒŽ(gu¨©)³•åQˆè¦è¾‘Öˆ°˜q™ä¸ªç›®çš„åªæœ‰åŠ å…¥ä¸€ä¸ªåªæœ‰ä¸€æ¡è§„则的 package åQ‰ã€?/span>
<!--[if !supportEmptyParas]-->
RuleBaseConfigurator å¯ä»¥æŒ‡å®š RuleBase çš„é™„åŠ è¡Œä¸ºã€‚åœ¨åŠ å…¥ RuleBase åŽï¼Œ RuleBaseConfiguration ž®±å˜æˆä¸å¯å˜å¯¹è±¡ã€?/span>
两个主è¦çš„属性是åQ?/span> PROPERT_ASSERT_BEHAVIOR å’?/span> PROPERTY_LOGICAL_OVERRIDE_BEHAVIOR åQˆåœ¨ä»¥åŽçš„部分ä¸ä¼?x¨¬)解释ï¼?j¨ª)。所有的属性值都æ˜?/span> RuleBaseConfiguration ¾cÖM¸çš„é™(r¨´n)æ€åŸŸå¸”R‡ã€?/span>
WorkingMemory 是è¿è¡Œæ—¶è§„则引擎的主è¦ç±»ã€‚å®ƒä¿æŒäº?ji¨£n)所有被 asserted ˜q?/span> WorkingMemory 的数æ®çš„引用åQŒç›´åˆ°å–消( retracted åQ‰ã€?/span> WorkingMemory 是有状æ€å¯¹è±¡ã€‚它们的生命周期å¯é•¿å¯çŸã€‚如果从一个çŸç”Ÿå‘½å‘¨æœŸçš„角度æ¥åŒä¸€ä¸ªå¼•擎进行交互,æ„味ç€ä½ å¯ä»¥ä‹Éç”?/span> RuleBase 对象æ¥äØ“(f¨´)æ¯ä¸ª session 产生一个新çš?/span> WorkingMemory åQŒç„¶åŽåœ¨¾l“æŸ session å?/span> discard ˜q™ä¸ª WorkingMemory åQˆäñ”生一ä¸?/span> WorkingMemory 是一个廉ä»ïL(f¨¥ng)š„æ“ä½œåQ‰ã€‚å¦ä¸€¿UåÅžå¼ï¼Œž®±æ˜¯åœ¨ä¸€ä¸ªç›¸å½“长的时间ä¸åQˆä¾‹å¦‚一ä¸?/span> conversation åQ‰ï¼Œä¿æŒä¸€ä¸?/span> WorkingMemory åQŒåƈ且对于新çš?/span> facts ä¿æŒæŒç®‹çš„æ›´æ–°ã€‚å½“ä½ å¸Œæœ?/span> dispose 一ä¸?/span> WorkingMemory 的时候,最好的实践ž®±æ˜¯è°ƒç”¨ dispose() æ–ÒŽ(gu¨©)³•åQŒæ¤æ—?/span> RuleBase ä¸å¯¹å®ƒçš„引用ž®†ä¼š(x¨¬)被移除(ž®½ç®¡˜q™æ˜¯ä¸€ä¸ªå¼±å¼•用åQ‰ã€‚ä¸½Ž¡æ€Žæ ·æœ€åŽå®ƒ?y¨u)®†ä¼?x¨¬)被当æˆåžƒåœ¾æ”¶é›†æŽ‰ã€‚术è¯?/span> WorkingMemory Actions 代表äº?ji¨£n)å¯?/span> WorkingMemory çš?/span> assertions åQ?/span> retractions å’?/span> modifications ã€?/span>
4.1 Facts
Facts æ˜¯ä»Žä½ çš„åº”ç”¨ä¸ï¼Œè¢?/span> assert ˜q?/span> WorkingMemory ä¸çš„对象åQ?/span> beans åQ‰ã€?/span> Facts 是规则å¯ä»¥è®¿é—®çš„ä»ÀL„çš?/span> java 对象。规则引擎ä¸çš?/span> facts òq¶ä¸æ˜¯â€?/span> clone â€?/span> facts åQŒå®ƒåªæ˜¯æŒæœ‰åˆîC½ çš„åº”ç”¨ä¸æ•°æ®çš„引用ã€?/span> Facts æ˜¯ä½ çš„åº”ç”¨æ•°æ®ã€?/span> String 和其他没æœ?/span> getter å’?/span> setter çš„ç±»ä¸æ˜¯æœ‰æ•ˆçš?/span> Fact 。这æ ïL(f¨¥ng)š„¾cÖM¸èƒ½ä‹É用域¾U¦æŸåQ?/span> Field Constraints åQ‰ï¼Œå› 䨓(f¨´)使用域约æŸè¦ä¾é JavaBean æ ‡å‡†çš?/span> getter å’?/span> setter æ¥åŒå¯¹è±¡äº¤äº’ã€?/span>
4.2 Assertion
“Assertionâ€?/span> 是将 facts 告诉 WorkingMemory 的动作,例如 WorkingMemory.assertObject (yourObject) 。当ä½?/span> assert 一ä¸?/span> fact åQŒå®ƒ?y¨u)®†è¢«‹‚€(g¨¨)查是å¦åŒ¹é…规则。这æ„å‘³ç€æ‰€æœ‰çš„匚w…工作ž®†ä¼š(x¨¬)åœ?/span> assert 的过½E‹ä¸å®Œæˆã€‚å°½½Ž¡å¦‚æ¤ï¼Œå½“ä½ å®Œæˆ assert facts 之åŽåQŒä½ ˜q˜è¦è°ƒç”¨â€?/span> fireAllRules() â€æ–¹æ³•æ¥æ‰§è¡Œè§„则ã€?/span>
当一个对象被 assert åŽï¼Œä¼?x¨¬)返回一ä¸?/span> FactHandle 。这ä¸?/span> FactHandle 是一个代表在 Working Memory ä¸ä½ çš?/span> asserted Object çš„ä×o(h¨´)牌( token åQ‰ã€‚å½“ä½ å¸Œæœ?/span> retract 或è€?/span> modify 一个对象的时候,˜q™ä¸ªä»¤ç‰Œè®©ä½ 用æ¥å?/span> WorkingMemory ˜q›è¡Œäº¤äº’ã€?/span>
WorkingMeomry 有两¿U?/span> assertion 模å¼åQ?/span> Equality å’?/span> Identity åQˆé»˜è®¤æ˜¯ Identity åQ‰ã€?/span>
Identity 模å¼ä¸?/span> WorkingMemory 使用一ä¸?/span> IdentityHashMap æ¥å˜å‚¨æ‰€æœ‰çš„ asserted Objects 。这个模å¼ä¸‹åQŒå½“ asserted çš?/span> Object 是åŒä¸€ä¸ªå®žä¾‹æ—¶åQŒå®ƒ˜q”回åŒä¸€ä¸?/span> FactHandle ã€?/span>
Equality 模å¼ä¸?/span> WorkingMemory 使用一ä¸?/span> HashMap æ¥å˜å‚¨æ‰€æœ‰çš„ asserted Objects 。这个模å¼ä¸‹åQŒå½“ asserted çš?/span> Object ç›¸ç‰æ—Óž¼Œå®ƒè¿”回åŒä¸€ä¸?/span> FactHandle ã€?/span>
åQ?/span> WorkingMemory.assertObject(yourObjcet) åªæ˜¯˜q›è¡Œ assertion 的一¿U?/span> regular æ–ÒŽ(gu¨©)³•åQŒè¿˜å˜åœ¨æœ‰ä¸€¿Uç§°ä¸?/span> logical assertion 的动作)(j¨ª)ã€?/span>
4.3 Retraction
基本上就æ˜?/span> assert 的逆æ“作。当ä½?/span> retract 一ä¸?/span> fact åQ?/span> WorkingMemory ž®†ä¸å†è·Ÿítªé‚£ä¸?/span> fact 。ä“Q何被 activated òq¶ä¾èµ–é‚£ä¸?/span> fact çš„è§„åˆ™å°†è¢«å–æ¶ˆã€‚注æ„:(x¨¬)完全有å¯èƒ½å˜åœ¨æŸæ¡è§„则是ä¾èµ–于一ä¸?/span> fact 的“ä¸å˜åœ¨â€ï¼ˆ non existence åQ‰ã€‚在˜q™ç§æƒ…况下, retract 一ä¸?/span> fact ž®†å¯¼è‡´ä¸€æ¡è§„则被‹È€‹z…R€‚对一ä¸?/span> Fact ˜q›è¡Œ Retraction åQŒå¿…™åÈ”¨ assert 时返回的那个 FactHandle åšäØ“(f¨´)傿•°ã€?/span>
4.4 Modification
当一ä¸?/span> Fact 被修改了(ji¨£n)åQŒä¼š(x¨¬)通知规则引擎˜q›è¡Œé‡æ–°å¤„ç†ã€‚在规则引擎内部实际上是å¯ÒŽ(gu¨©)—§çš?/span> Fact ˜q›è¡Œ retract åQŒç„¶åŽå¯¹æ–°çš„ Object å†è¿›è¡?/span> assert 。è¦ä½¿ç”¨ modifyObject() æ–ÒŽ(gu¨©)³•æ¥é€šçŸ¥ Working Memory åQŒè¢«æ”¹å˜çš?/span> Object òq¶ä¸ä¼?x¨¬)自己通知规则引擎。注æ„:(x¨¬) modifyObject() æ–ÒŽ(gu¨©)³•æ€ÀL˜¯è¦æŠŠè¢«ä¿®æ”¹çš„ Object åšäØ“(f¨´)½W¬äºŒå‚æ•°åQŒè¿™ž®±å…è®æ€½ 把一个ä¸å¯å˜å¯¹è±¡æ›¿æ¢ä¸ºå¦ä¸€ä¸ªæ–°å¯¹è±¡ã€?/span>
4.5 Globals
Global æ˜¯ä¸€ä¸ªèƒ½å¤Ÿè¢«ä¼ è¿› WorkingMemory 但ä¸éœ€è¦?/span> assert 的命å对象。大多数˜q™äº›å¯¹è±¡è¢«ç”¨æ¥ä½œä¸ºé™(r¨´n)æ€ä¿¡æ¯æˆ–æœåŠ¡ã€‚è¿™äº›æœåŠ¡è¢«ç”¨åœ¨ä¸€æ¡è§„则的 RHS åQŒæˆ–者å¯èƒ½æ˜¯ä»Žè§„则引擎返回对象的一¿U方法ã€?/span>
setGlobal() æ–ÒŽ(gu¨©)³•ä¼ è¿›åŽÈš„命å对象必须å?/span> RuleBase 䏿‰€å®šä¹‰çš„具有相åŒçš„¾cÕdž‹åQˆå°±æ˜¯è¦åŒä½ 的规则文件ä¸ç”?/span> Global 关键嗿‰€å®šä¹‰çš„类型相åŒï¼‰(j¨ª)åQŒå¦åˆ™ä¼š(x¨¬)抛出一ä¸?/span> RuntimeException 。如果一æ¡è§„则在ä½?/span> setGlobal 之å‰è°ƒç”¨äº?ji¨£n)定义çš?/span> Global åQŒä¼š(x¨¬)抛出一ä¸?/span> NullPointerException ã€?/span>
4.6 Property Change Listener
å¦‚æžœä½ çš„ fact 对象æ˜?/span> JavaBean åQŒä½ å¯ä»¥ä¸ºå®ƒä»¬å®žçŽîC¸€ä¸?/span> property change listener åQŒç„¶åŽæŠŠå®ƒå‘Šè¯‰è§„åˆ™å¼•æ“Žã€‚è¿™æ„味ç€åQŒå½“一ä¸?/span> fact æ”¹å˜æ—Óž¼Œè§„则引擎ž®†ä¼š(x¨¬)自动知é“åQŒåƈ˜q›è¡Œå“åº”çš„åŠ¨ä½œï¼ˆä½ ä¸éœ€è¦è°ƒç”?/span> modifyObject() æ–ÒŽ(gu¨©)³•æ¥é€šçŸ¥ WorkingMemory åQ‰ã€?/span> Proxy libraries ž®†ä¼š(x¨¬)帮助实现˜q™ä¸€åˆ‡ã€‚è¦è®?/span> Property Change Listener 生效åQŒè¿˜è¦å°† fact 讄¡½®ä¸ºåЍæ€ï¼ˆ dynamic åQ‰æ¨¡å¼ï¼Œé€šè¿‡ž®?/span> true åšäØ“(f¨´) assertObject() æ–ÒŽ(gu¨©)³•çš„ç¬¬äºŒä¸ªå‚æ•°æ¥å®žçŽŽÍ¼š(x¨¬)
ç„¶åŽè¦åœ¨ JavaBean ä¸åР入䏀ä¸?/span> PropertyChangeSupport 实例åQŒå’Œä¸¤ä¸ªæ–ÒŽ(gu¨©)³•åQ?/span> addPropertyChangeListener() å’?/span> removePropertyChangeListener() 。最åŽè¦åœ?/span> JavaBean çš?/span> setter æ–ÒŽ(gu¨©)³•ä¸é€šçŸ¥ PropertyChangeSupport 所å‘生的å˜åŒ–。示例代ç 如下:(x¨¬)
Agenda æ˜?/span> RETE 的一个特ç‚V€‚在一ä¸?/span> WorkingMemory Action å‘生æ—Óž¼Œå¯èƒ½ä¼?x¨¬)有多æ¡è§„则å‘生完全匚w…。当一æ¡è§„则完全匹é…的时候,一ä¸?/span> Activation ž®Þp¢«åˆ›å¾åQˆå¼•用了(ji¨£n)˜q™æ¡è§„则和与其匹é…çš„ facts åQ‰ï¼Œç„¶åŽæ”¾è¿› Agenda ä¸ã€?/span> Agenda 通过使用冲çªè§£å†³½{–ç•¥åQ?/span> Conflict Resolution Strategy åQ‰æ¥å®‰æŽ’˜q™äº› Activations 的执行ã€?/span>
引擎工作在一个â€?/span> 2 é˜¶æ®µâ€æ¨¡å¼ä¸‹åQ?/span>
<!--[if !supportLists]--> 1åQ?span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal"> <!--[endif]--> WorkingMemory Actions åQ?/span>assertæ–°çš„factsåQŒä¿®æ”¹å˜åœ¨çš„factså’?/span>retract facts都是WorkingMemory Actions。通过在应用程åºä¸è°ƒç”¨fireAllRules()æ–ÒŽ(gu¨©)³•åQŒä¼š(x¨¬)使引擎è{æ¢åˆ°Agenda Evaluatioin阶段ã€?/span>
<!--[if !supportLists]--> 2åQ?span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal"> <!--[endif]--> Agenda Evaluation åQšå°è¯•选择一æ¡è§„则进行激å‘(fireåQ‰ã€‚如果规则没有找到就退出,å¦åˆ™å®ƒå°±ž®è¯•‹È€å‘è¿™æ¡è§„则,然åŽè½¬æ¢åˆ?/span>WorkingMemory Actions阶段åQŒç›´åˆ?/span>Agendaä¸äØ“(f¨´)½Iºã€?/span>
˜q™ä¸ª˜q‡ç¨‹ä¸€ç›´é‡å¤ï¼Œç›´åˆ° Agenda æ˜¯ç©ºçš„ï¼Œæ¤æ—¶æŽ§åˆ¶æƒå°±å›žåˆ°åº”用½E‹åºä¸ã€‚。当 WorkingMemory Actions å‘生æ—Óž¼Œæ²¡æœ‰è§„则æ£åœ¨è¢«æ¿€å‘ã€?/span>
下图说明äº?ji¨£n)这个åó@环的˜q‡ç¨‹åQ?/span>
Figure 5.2 . Two Phase Execution
5
åQ?/span>
1 Conflict Resultion
å½“æœ‰å¤šæ¡ rules åœ?/span> agenda ä¸ï¼Œž®±éœ€è¦è§£å†›_†²½H。当‹È€å‘一æ¡è§„则时åQŒä¼š(x¨¬)å¯?/span> WorkingMemory 产生副作用。规则引擎需è¦çŸ¥é“规则è¦ä»¥ä»€ä¹ˆé¡ºåºæ¥‹È€å‘(例如åQŒæ¿€å?/span> rule A å¯èƒ½ä¼?x¨¬)引è?/span> rule B 被从 agenda ä¸ç§»é™¤ã€‚)(j¨ª)
Drools 采å–的冲½H解决ç–略有 2 ¿U,按照优先¾U§æŽ’列如下:(x¨¬) Salience åQ?/span> LIFO åQˆåŽ˜q›å…ˆå‡ºï¼‰(j¨ª)。最易懂的ç–略是â€?/span> Salience â€ï¼Œå³ä¼˜å…ˆçñ”åQ?/span> user å¯ä»¥ä¸ºæŸä¸?/span> rule 指定一个高一点的优先¾U§ï¼ˆé€šè¿‡é™„给它一个比较大的数å—)(j¨ª)。高 Salience çš?/span> rule ž®†ä¼š(x¨¬)被优先激å‘ã€?/span>
5
åQ?/span>
2 Agenda Groups
Agenda Groups 是划åˆ?/span> Agenda ä¸?/span> rules åQˆå…¶å®žæ˜¯â€?/span> activations â€ï¼‰(j¨ª)的一¿U方法。在ä»ÀL„ä¸€ä¸ªæ—¶åˆ»ï¼Œåªæœ‰ä¸€ä¸?/span> group 拥有â€?/span> focus â€ï¼Œ˜q™æ„味ç€åªæœ‰åœ¨é‚£ä¸?/span> group ä¸çš„ activations æ‰æ˜¯æœ‰æ•ˆçš„ã€?/span>
Agenda Groups 是在 grouped rules 之间创å¾ä¸€ä¸ªâ€œæµâ€ï¼ˆ flow åQ‰çš„½Ž€ä¾¿çš„æ–ÒŽ(gu¨©)³•ã€‚ä½ å¯ä»¥åœ¨è§„则引擎ä¸åQŒæˆ–是用 API æ¥åˆ‡æ¢å…·æœ‰ç„¦ç‚¹çš„¾l„ã€‚å¦‚æžœä½ çš„è§„åˆ™æœ‰å¾ˆæ˜Ž¼‹®çš„多“阶ŒDµâ€ï¼ˆ phases åQ‰æˆ–多“åºåˆ—â€ï¼ˆ sequences åQ‰çš„处ç†åQŒå¯ä»¥è€ƒè™‘ç”?/span> Agenda Groups æ¥è¾¾åˆ°è¿™ä¸ªç›®çš„ã€?/span>
æ¯æ¬¡è°ƒç”¨ setFocus() æ–ÒŽ(gu¨©)³•的时候,那个 Agenda Group ž®×ƒ¼š(x¨¬)è¢«åŽ‹å…¥ä¸€ä¸ªå †æ ˆï¼Œå½“è¿™ä¸ªæœ‰ç„¦ç‚¹çš„ç»„ä¸ºç©ºæ—Óž¼Œå®ƒå°±ä¼?x¨¬)被弹出åQŒç„¶åŽä¸‹ä¸€ä¸ªç»„ž®×ƒ¼š(x¨¬)被执行。一ä¸?/span> Agenda Group å¯ä»¥å‡ºçŽ°åœ¨å †æ ˆçš„å¤šä¸ªä½ç½®ã€‚默认的 Agenda Group 是â€?/span> MAIN â€ï¼Œæ‰€æœ‰æ²¡æœ‰è¢«æŒ‡å®š Agenda Group çš?/span> Activations 都被攑ֈ°é‚£ä¸ª¾l„ä¸åQŒè¿™ä¸ªç»„æ€ÀL˜¯è¢«æ”¾åœ¨å †æ ˆçš„½W¬ä¸€ä¸ªç»„åQŒåƈ默认¾l™äºˆç„¦ç‚¹ã€?/span>
5
åQ?/span>
3Â Agenda Filters
Filter 必须实现 AgendaFilter 接å£åQŒç”¨æ¥å…许或¼›æ¢ä¸€ä¸?/span> activation 能够被激å‘ã€?/span> Drools æä¾›äº?ji¨£n)下é¢å‡ ¿U方便的默认实现åQ?/span>
<!--[if !supportLists]--> ·        <!--[endif]--> RuleNameEndWithAgendaFilter
<!--[if !supportLists]--> ·        <!--[endif]--> RuleNameEqualsAgendaFilter
<!--[if !supportLists]--> ·        <!--[endif]--> RuleNameStartsWithAgendaFilter
è¦ä‹É用一ä¸?/span> filter ž®Þp¦åœ¨è°ƒç”?/span> fireAllRules() æ–ÒŽ(gu¨©)³•的时候指定它。下é¢çš„例垮†å¯¹æ‰€æœ‰åå—以â€?/span> Test â€ç»“ž®„¡š„规则˜q›è¡Œ˜q‡æ×o(h¨´)åQ?/span>
6åQŽäº‹ä»¶æ¨¡åž‹ï¼ˆ Event Model åQ?/span>
Event 包里æä¾›äº?ji¨£n)规则引擎的事äšg机制åQŒåŒ…括规则激å‘,对象è¢?/span> asserted ½{‰ç‰ã€‚ä½ å¯ä»¥ä½¿ç”¨äº‹äšg机制æ¥è¿›è¡?/span> AOP ¾~–程ã€?/span>
有两¿U类型的 Event Listener åQ?/span> WorkingMemoryEventListener å’?/span> AgendaEventListener ã€?/span>
对两ä¸?/span> EventListener 接å£éƒ½æä¾›äº†(ji¨£n)默认实现åQŒä½†åœ¨æ–¹æ³•ä¸òq¶æ²¡æœ‰åšä»ÖM½•äº‹ã€‚ä½ å¯ä»¥¾l§æ‰¿˜q™ä¸¤ä¸ªé»˜è®¤å®žçްæ¥å®Œæˆä½ 自å·Þqš„实现åQ?/span> DefaultAgendaEventListener å’?/span> DefaultWorkingMemoryEventListener 。下é¢ä»£ç 说明了(ji¨£n)如何扩展一ä¸?/span> DefaultAgendaEventListner òq¶æŠŠå®ƒåŠ åˆ?/span> WorkingMemory ä¸ï¼Œä¾‹åä¸åªå®Œæˆäº?/span> afterActivationFired() æ–ÒŽ(gu¨©)³•åQ?/span>
Drools 也æä¾›äº†(ji¨£n) DebugWorkingMemoryEventListener å’?/span> DebugAgendaEventListener 两个实现¾c»ï¼Œåœ¨è¿™ä¸¤ä¸ª¾cÈš„æ–ÒŽ(gu¨©)³•ä¸å®žçŽîCº†(ji¨£n) debug ä¿¡æ¯çš„输出:(x¨¬)
Rete 在拉ä¸è¯ä¸æ˜¯ â€netâ€?/span> åQŒæœ‰¾|‘ç»œçš„æ„æ€ã€?/span> RETE ½Ž—法å¯ä»¥åˆ†äØ“(f¨´)两部分:(x¨¬)规则¾~–译åQ?/span> rule compilation åQ‰å’Œ˜q行时执行( runtime execution åQ‰ã€?/span>
¾~–译½Ž—法æè¿°äº?ji¨£n)规则如何åœ?/span> Production Memory ä¸äñ”生一个有效的辨别¾|‘ç»œã€‚ç”¨ä¸€ä¸ªéžæŠ€æœ¯æ€§çš„è¯æ¥è¯ß_(d¨¢)¼Œä¸€ä¸ªèöL别网¾lœå°±æ˜¯ç”¨æ¥è¿‡æ»¤æ•°æ®ã€‚方法是通过数æ®åœ¨ç½‘¾lœä¸çš„ä¼ æ’æ¥˜q‡æ×o(h¨´)æ•°æ®ã€‚在™å¶ç«¯èŠ‚ç‚¹ž®†ä¼š(x¨¬)有很多匹é…的数æ®ã€‚当我们™åºç€¾|‘络å‘下赎ͼŒåŒšw…的数æ®å°†ä¼?x¨¬)è¶Šæ¥è¶Šž®‘。在¾|‘络的最底部是终端节点( terminal nodes åQ‰ã€‚在 Dr Forgy çš?/span> 1982 òq´çš„论文ä¸ï¼Œä»–æ˜qîCº†(ji¨£n) 4 ¿U基本节点:(x¨¬) root , 1-input, 2-input and terminal 。下图是 Drools ä¸çš„ RETE 节点¾cÕdž‹åQ?/span>
Figure 1. Rete Nodes
æ ¹èŠ‚ç‚¹ï¼ˆ RootNode åQ‰æ˜¯æ‰€æœ‰çš„对象˜q›å…¥¾|‘络的入å£ã€‚ç„¶åŽï¼Œä»Žæ ¹èŠ‚ç‚¹ç«‹å³˜q›å…¥åˆ?/span> ObjectTypeNode ã€?/span> ObjectTypeNode 的作用是使引擎åªåšå®ƒéœ€è¦åšçš„事情。例如,我们有两个对象集åQ?/span> Account å’?/span> Order 。如果规则引擎需è¦å¯¹æ¯ä¸ªå¯¹è±¡éƒ½è¿›è¡Œä¸€ä¸ªå‘¨æœŸçš„评估åQŒé‚£ä¼?x¨¬)浪费很多的旉™—´ã€‚䨓(f¨´)äº?ji¨£n)æé«˜æ•ˆçŽ‡ï¼Œå¼•æ“Žž®†åªè®©åŒ¹é?/span> object type 的对象通过到达节点。通过˜q™ç§æ–ÒŽ(gu¨©)³•åQŒå¦‚果一个应ç”?/span> assert 一个新çš?/span> account åQŒå®ƒä¸ä¼š(x¨¬)ž®?/span> Order å¯¹è±¡ä¼ é€’åˆ°èŠ‚ç‚¹ä¸ã€‚很多现ä»?/span> RETE 实现都有专门çš?/span> ObjectTypeNode 。在一些情况下åQ?/span> ObjectTypeNode 被用散列法进一æ¥ä¼˜åŒ–ã€?/span>
Figure 2 . ObjectTypeNodes
ObjectTypeNode èƒ½å¤Ÿä¼ æ’åˆ?/span> AlphaNodes, LeftInputAdapterNodes å’?/span> BetaNodes ã€?/span>
1-input 节点通常被称ä¸?/span> AlphaNode ã€?/span> AlphaNodes 被用æ¥è¯„ä¼°å—颿¡ä»Óž¼ˆ literal conditions åQ‰ã€‚虽ç„?d¨°ng)ž¼?/span> 1982 òq´çš„è®ºæ–‡åªæåˆîCº†(ji¨£n)ç›¸ç‰æ¡äšgåQˆæŒ‡çš„å—é¢ä¸Šç›¸ç‰åQ‰ï¼Œå¾ˆå¤š RETE 实现支æŒå…¶ä»–çš„æ“作。例如, Account.name = = “Mr Troutâ€? 是一个å—颿¡ä»¶ã€‚当一æ¡è§„则对于一¿U?/span> object type 有多æ¡çš„å—颿¡äšgåQŒè¿™äº›å—颿¡ä»¶å°†è¢«é“¾æŽ¥åœ¨ä¸€èµ—÷€‚这是说åQŒå¦‚果一个应ç”?/span> assert 一ä¸?/span> account 对象åQŒåœ¨å®ƒèƒ½åˆ°è¾¾ä¸‹ä¸€ä¸?/span> AlphaNode 之å‰åQŒå®ƒå¿…须先满‘³ç¬¬ä¸€ä¸ªå—颿¡ä»¶ã€‚在 Dr. Forgy 的论文ä¸åQŒä»–ç”?/span> IntraElement conditions æ¥è¡¨˜q°ã€‚下é¢çš„图说明了(ji¨£n) Cheese çš?/span> AlphaNode ¾l„åˆåQ?/span> name = = “cheddarâ€?/span> åQ?/span> strength = = “strongâ€?/span> åQ‰ï¼š(x¨¬)
Figure 3. AlphaNodes
Drools 通过散列法优化了(ji¨£n)ä»?/span> ObjectTypeNode åˆ?/span> AlphaNode çš„ä¼ æ’。毋ơ一ä¸?/span> AlphaNode è¢«åŠ åˆîC¸€ä¸?/span> ObjectTypeNode 的时候,ž®×ƒ»¥å—é¢å€û|¼ˆ literal value åQ‰ä½œä¸?/span> key åQŒä»¥ AlphaNode ä½œäØ“(f¨´) value åŠ å…¥ HashMap 。当一个新的实例进å…?/span> ObjectTypeNode 的时候,ä¸ç”¨ä¼ 递到æ¯ä¸€ä¸?/span> AlphaNode åQŒå®ƒå¯ä»¥ç›´æŽ¥ä»?/span> HashMap ä¸èŽ·å¾—æ£¼‹®çš„ AlphaNode åQŒé¿å…了(ji¨£n)ä¸å¿…è¦çš„å—颋‚€(g¨¨)查ã€?/span>
<!--[if !supportEmptyParas]-->
2-input 节点通常被称ä¸?/span> BetaNode ã€?/span> Drools 䏿œ‰ä¸¤ç§ BetaNode åQ?/span> JoinNode å’?/span> NotNode ã€?/span> BetaNodes 被用æ¥å¯¹ 2 个对象进行对比。这两个对象å¯ä»¥æ˜¯åŒ¿U类型,也å¯ä»¥æ˜¯ä¸åŒ¾cÕdž‹ã€?/span>
我们¾U¦å®š BetaNodes çš?/span> 2 个输入称为左边( left åQ‰å’ŒåŒ™¾¹åQ?/span> right åQ‰ã€‚一ä¸?/span> BetaNode 的左边输入通常æ˜?/span> a list of objects 。在 Drools ä¸ï¼Œ˜q™æ˜¯ä¸€ä¸ªæ•°¾l„。å³è¾¹è¾“入是 a single object 。两ä¸?/span> NotNode å¯ä»¥å®Œæˆâ€?/span> exists ’检查ã€?/span> Drools 通过ž®†çƒ¦(ch¨³)引应用在 BetaNodes 上扩展了(ji¨£n) RETE ½Ž—法。下囑ֱ•½CÞZº†(ji¨£n)一ä¸?/span> JoinNode çš„ä‹É用:(x¨¬)
Figure 4 . JoinNode
注æ„到图ä¸çš„左边输入用到äº?ji¨£n)一ä¸?/span> LeftInputAdapterNode åQŒè¿™ä¸ªèŠ‚ç‚¹çš„ä½œç”¨æ˜¯å°†ä¸€ä¸?/span> single Object 转化ä¸ÞZ¸€ä¸ªå•对象数组åQ?/span> single Object Tuple åQ‰ï¼Œä¼ æ’åˆ?/span> JoinNode èŠ‚ç‚¹ã€‚å› ä¸ºæˆ‘ä»¬ä¸Šé¢æåˆ°è¿‡å·¦è¾¹è¾“å…¥é€šå¸¸æ˜?/span> a list of objects ã€?/span>
<!--[if !supportEmptyParas]-->
Terminal nodes 被用æ¥è¡¨æ˜Žä¸€æ¡è§„则已¾l匹é…了(ji¨£n)它的所有æ¡ä»Óž¼ˆ conditions åQ‰ã€?/span> 在这点,我们说这æ¡è§„则有äº?ji¨£n)一个完全匹é…( full match åQ‰ã€‚在一些情况下åQŒä¸€æ¡å¸¦æœ‰â€œæˆ–â€æ¡ä»¶çš„规则å¯ä»¥æœ‰è¶…˜q‡ä¸€ä¸ªçš„ terminal node ã€?/span>
Drools é€šè¿‡èŠ‚ç‚¹çš„å…±äº«æ¥æé«˜è§„åˆ™å¼•æ“Žçš„æ€§èƒ½ã€‚å› ä¸ºå¾ˆå¤šçš„è§„åˆ™å¯èƒ½å˜åœ¨éƒ¨åˆ†ç›¸åŒçš„æ¨¡å¼ï¼ŒèŠ‚ç‚¹çš„å…±äº«å…许我们对内å˜ä¸çš„节点数釘q›è¡ŒåŽ‹ç¾ƒåQŒä»¥æä¾›é历节点的过½E‹ã€‚下é¢çš„两个规则ž®±å…±äº«äº†(ji¨£n)部分节点åQ?/span>
˜q™é‡Œæˆ‘ä»¬å…ˆä¸æŽ¢è®¨˜q™ä¸¤æ?/span> rule åˆ°çš„æ˜¯ä»€ä¹ˆæ„æ€ï¼Œå•从一个直观的感觉åQŒè¿™ä¸¤æ¡ rule 在它们的 LHS ä¸åŸºæœ¬éƒ½æ˜¯ä¸€æ ïL(f¨¥ng)š„åQŒåªæ˜¯æœ€åŽçš„ favouriteCheese åQŒä¸€æ¡è§„则是½{‰äºŽ $cheddar åQŒè€Œå¦ä¸€æ¡è§„则是ä¸ç‰äº?/span> $cheddar ã€‚ä¸‹é¢æ˜¯˜q™ä¸¤æ¡è§„则的节点图:(x¨¬)
Figure 5 . Node Sharing
从图上å¯ä»¥çœ‹åˆŽÍ¼Œ¾~–译åŽçš„ RETE ¾|‘络ä¸ï¼Œ AlphaNode 是共享的åQŒè€?/span> BetaNode 䏿˜¯å…׃ín的。上é¢è¯´çš„相½{‰å’Œä¸ç›¸½{‰å°±ä½“现åœ?/span> BetaNode çš„ä¸åŒã€‚ç„¶åŽè¿™ä¸¤æ¡è§„则有å„自的 Terminal Node ã€?/span>
<!--[if !supportEmptyParas]-->
RETE ½Ž—法的第二个部分是è¿è¡Œæ—¶åQ?/span> runtime åQ‰ã€‚当一个应ç”?/span> assert 一个对象,引擎ž®†æ•°æ®ä¼ 递到 root node 。从那里åQŒå®ƒ˜q›å…¥ ObjectTypeNode òq¶æ²¿ç€¾|‘络å‘ä¸‹ä¼ æ’。当数æ®åŒšw…一个节点的æ¡äšgåQŒèŠ‚ç‚¹å°±ž®†å®ƒè®°å½•到相应的内å˜ä¸ã€‚è¿™æ ·åšçš„åŽŸå› æœ‰ä»¥ä¸‹å‡ ç‚¹åQšä¸»è¦çš„åŽŸå› æ˜¯å¯ä»¥å¸¦æ¥æ›´å¿«çš„æ€§èƒ½ã€‚虽然记ä½å®Œå…¨æˆ–部分匚w…的对象需è¦å†…å˜ï¼Œå®ƒæä¾›äº†(ji¨£n)速度和å¯ä¼¸ç¾ƒæ€§çš„特点。当一æ¡è§„则的所有æ¡ä»‰™ƒ½æ»¡èƒöåQŒè¿™ž®±æ˜¯å®Œå…¨åŒšw…ã€‚è€Œåªæœ‰éƒ¨åˆ†æ¡ä»¶æ»¡‘»I¼Œž®±æ˜¯éƒ¨åˆ†åŒšw…。(我觉得引擎在æ¯ä¸ªèŠ‚ç‚¹éƒ½æœ‰å…¶å¯¹åº”çš„å†…å˜æ¥å‚¨å˜æ»¡‘Œ™¯¥èŠ‚ç‚¹æ¡äšg的对象,˜q™å°±é€ æˆäº?ji¨£n)如果一个对象是完全匚w…åQŒé‚£˜q™ä¸ªå¯¹è±¡ž®×ƒ¼š(x¨¬)在æ¯ä¸ªèŠ‚ç‚¹çš„å¯¹åº”å†…å˜ä¸éƒ½å˜æœ‰å…¶æ˜ 象。)(j¨ª)
2. Leaps ½Ž—法åQ?/span>
Production systems çš?/span> Leaps ½Ž—法使用äº?ji¨£n)一¿Uâ€?/span> lazy â€æ–¹æ³•æ¥è¯„ä¼°æ¡äšgåQ?/span> conditions åQ‰ã€‚一¿U?/span> Leaps ½Ž—法的修改版本的实现åQŒä½œä¸?/span> Drools v3 的一部分åQŒå°è¯•结å?/span> Leaps å’?/span> RETE æ–ÒŽ(gu¨©)³•的最好的特点æ¥å¤„ç?/span> Working Memory ä¸çš„ facts ã€?/span>
å¤å…¸çš?/span> Leaps æ–ÒŽ(gu¨©)³•ž®†æ‰€æœ‰çš„ asserted çš?/span> facts åQŒæŒ‰ç…§å…¶è¢?/span> asserted åœ?/span> Working Memory ä¸çš„™åºåºåQ?/span> FIFO åQ‰ï¼Œæ”‘Öœ¨ä¸Õd †æ ˆä¸ã€‚它一个个的检æŸ?/span> facts åQŒé€šè¿‡˜q代匚w… data type çš?/span> facts é›†åˆæ¥æ‰¾å‡ºæ¯ä¸€ä¸ªç›¸å…Œ™§„则的匚w…。当一个匹é…的数æ®è¢«å‘现时åQŒç³»¾lŸè®°ä½æ¤æ—¶çš„˜q代ä½ç½®ä»¥å¤‡å¾…会(x¨¬)çš„ç‘ô¾lè„P代,òq¶ä¸”‹È€å‘规则结果( consequence åQ‰ã€‚当¾l“æžœåQ?/span> consequence åQ‰æ‰§è¡Œå®Œæˆä»¥åŽï¼Œ¾pÈ»Ÿž®×ƒ¼š(x¨¬)¾l§ç®‹å¤„ç†å¤„于ä¸Õd †æ ˆé¡¶éƒ¨çš„ fact 。如æ¤åå¤ã€?/span>
Rules
      一æ¡è§„则是对商业知识的¾~–ç 。一æ¡è§„则有 attributes åQŒä¸€ä¸?/span> Left Hand Side åQ?/span> LHS åQ‰å’Œä¸€ä¸?/span> Right Hand Side åQ?/span> RHS åQ‰ã€?/span> Drools å…è®¸ä¸‹åˆ—å‡ ç§ attributes åQ?/span> salience åQ?/span> agenda-group åQ?/span> no-loop åQ?/span> auto-focus åQ?/span> duration åQ?/font> activation-group ã€?/span>
      规则å¯ä»¥é€šè¿‡ package 关键å—åŒä¸€ä¸ªå‘½å空é—ß_(d¨¢)¼ˆ namespace åQ‰ç›¸å…Œ™”åQ›å…¶ä»–的规则引擎å¯èƒ½¿U°æ¤ä¸ø™§„则集åQ?/span> Rule Set åQ‰ã€‚一ä¸?/span> package 声明äº?/span> imports åQ?/span> global å˜é‡åQ?/span> functions å’?/span> rules ã€?/span>
      å¯ÒŽ(gu¨©)–°çš„æ•°æ®å’Œè¢«ä¿®æ”¹çš„æ•°æ®˜q›è¡Œè§„则的匹é…称为模å¼åŒ¹é…( Pattern Matching åQ‰ã€‚进行匹é…的引擎¿UîCØ“(f¨´)æŽ¨ç†æœºï¼ˆ Inference Engine åQ‰ã€‚被讉K—®çš„规则称ä¸?/span> ProductionMemory åQŒè¢«æŽ¨ç†æœø™¿›è¡ŒåŒ¹é…的数殿UîCØ“(f¨´) WorkingMemory ã€?/span> Agenda ½Ž¡ç†è¢«åŒ¹é…è§„åˆ™çš„æ‰§è¡Œã€‚æŽ¨ç†æœºæ‰€é‡‡ç”¨çš„æ¨¡å¼åŒ¹é…ç®—æ³•æœ‰ä¸‹åˆ—å‡ ç§åQ?/span> Linear åQ?/span> RETE åQ?/span> Treat åQ?/span> Leaps ã€?/span>
      Drools 采用äº?/span> RETE å’?/span> Leaps 的实现ã€?/span> Drools çš?/span> RETE 实现被称ä¸?/span> ReteOO åQŒè¡¨½C?/span> Drools å¯?/span> Rete ½Ž—法˜q›è¡Œäº?ji¨£n)åŠ å¼ºå’Œä¼˜åŒ–çš„å®žçŽ°ã€?/span>
      一æ¡è§„则的 LHS ç”?/span> Conditional Element 和域¾U¦æŸåQ?/span> Field Constraints åQ‰ã€‚下é¢çš„ä¾‹åæ˜„¡¤ºäº?ji¨£n)对一ä¸?/span> Cheese Fact 使用äº?ji¨£n)å—é¢åŸŸ¾U¦æŸåQ?/span> Literal Field Constraint åQ?/span>
上é¢çš„这个例åç±»ä¼égºŽåQ?/span>
      规则引擎实现äº?ji¨£n)æ•°æ®åŒé€»è¾‘çš„å®Œå…¨è§£è€¦ã€‚è§„åˆ™åÆˆä¸èƒ½è¢«ç›´æŽ¥è°ƒç”¨ï¼Œå› 䨓(f¨´)å®ƒä»¬ä¸æ˜¯æ–ÒŽ(gu¨©)³•或函敎ͼŒè§„åˆ™çš„æ¿€å‘æ˜¯å¯?/span> WorkingMemory 䏿•°æ®å˜åŒ–çš„å“应。结果( Consequence åQŒå³ RHS åQ‰ä½œä¸?/span> LHS events 完全匚w…çš?/span> Listener ã€?/span>
å½?/span> rules è¢«åŠ å…?/span> Productioin Memory åŽï¼Œ rules 被规则引擎用 RETE ½Ž—法分解æˆä¸€ä¸ªå›¾åQ?/span>
      å½?/span> Facts è¢?/span> assert ˜q›å…¥ WorkingMemory ä¸åŽåQŒè§„则引擎找到匹é…çš„ ObjectTypeNode åQŒç„¶åŽå°†æ?/span> Fact ä¼ æ’åˆîC¸‹ä¸€ä¸ªèŠ‚ç‚V€?/span> ObjectTypeNode 拥有一å—å†…å˜æ¥ä¿å˜æ‰€æœ‰åŒ¹é…çš„ facts 。在我们的例åä¸åQŒä¸‹ä¸€ä¸ªèŠ‚ç‚ÒŽ(gu¨©)˜¯ä¸€ä¸ªåŸŸ¾U¦æŸåQ?/span> Field Constraint åQ‰ï¼Œ type = = “cheddarâ€?/span> 。如果æŸä¸?/span> Cheese å¯¹è±¡çš„ç±»åž‹ä¸æ˜¯â€?/span> cheddar â€ï¼Œ˜q™ä¸ª fact ž®†ä¸ä¼?x¨¬)è¢«ä¼ æ’到网¾lœçš„下一个节ç‚V€‚如果是â€?/span> cheddar â€ç±»åž‹ï¼Œå®ƒå°†è¢«è®°å½•到 AlphaNode 的内å˜ä¸åQŒåÆˆä¼ æ’到网¾lœçš„下一个节ç‚V€?/span> AlphaNode 是å¤å…?/span> RETE 术è¯åQŒå®ƒæ˜¯ä¸€ä¸ªå•输入 / å•输出的节点。最åŽé€šè¿‡ AlphaNode çš?/span> fact è¢«ä¼ æ’到 Terminal Node ã€?/span> Terminal Node 是最¾lˆèŠ‚ç‚¹ï¼Œåˆ°æ¤æˆ‘们说这æ¡è§„则被完全匚w…åQŒåƈ准备‹È€å‘ã€?/span>
      当一æ¡è§„则被完全匚w…åQŒå®ƒòq¶æ²¡æœ‰ç«‹åˆ»è¢«‹È€å‘(åœ?/span> RETE 䏿˜¯˜q™æ ·åQŒä½†åœ?/span> Leaps ä¸å®ƒä¼?x¨¬)立刻被‹È€å‘)(j¨ª)。这æ¡è§„则和与其匚w…çš?/span> facts ž®†æ¿€‹z»è¢«æ”‘Ö…¥ Agenda åQŒç”± Agenda æ¥è´Ÿè´£å®‰æŽ’æ¿€å?/span> Activations åQˆæŒ‡çš„æ˜¯ rule + the matched facts åQ‰ã€?/span>
下é¢çš„图很清楚的说明äº?/span> Drools 规则引擎的执行过½E‹ï¼š(x¨¬)
   数æ®è¢?/span> assert ˜q?/span> WorkingMemory åŽï¼Œå’?/span> RuleBase ä¸çš„ rule ˜q›è¡ŒåŒšw…åQˆç¡®åˆ‡çš„说应该是 rule çš?/span> LHS åQ‰ï¼Œå¦‚果匚w…æˆåŠŸ˜q™æ¡ rule ˜qžåŒå’Œå®ƒåŒšw…的数æ®ï¼ˆæ¤æ—¶ž®±å«å?/span> Activation åQ‰ä¸€èµ¯‚¢«æ”‘Ö…¥ Agenda åQŒç‰å¾?/span> Agenda æ¥è´Ÿè´£å®‰æŽ’æ¿€å?/span> Activation åQˆå…¶å®žå°±æ˜¯æ‰§è¡?/span> rule çš?/span> RHS åQ‰ï¼Œä¸Šå›¾ä¸çš„è±åŞ部分ž®±æ˜¯åœ?/span> Agenda 䏿¥æ‰§è¡Œçš„, Agenda ž®×ƒ¼š(x¨¬)æ ÒŽ(gu¨©)®å†²çªè§£å†³½{–ç•¥æ¥å®‰æŽ?/span> Activation 的执行顺åºã€?/span>