隨筆 - 19, 文章 - 93, 評論 - 17, 引用 - 0
          數(shù)據(jù)加載中……

          (四): Drools規(guī)則引擎 (下)

          Drools 規(guī)則引擎(下)

          4 WorkingMemory:

          Figure 4.1 WorkingMemory

          WorkingMemory 是運(yùn)行時(shí)規(guī)則引擎的主要類。它保持了所有被 asserted 進(jìn) WorkingMemory 的數(shù)據(jù)的引用,直到取消( retracted )。 WorkingMemory 是有狀態(tài)對象。它們的生命周期可長可短。如果從一個(gè)短生命周期的角度來同一個(gè)引擎進(jìn)行交互,意味著你可以使用 RuleBase 對象來為每個(gè) session 產(chǎn)生一個(gè)新的 WorkingMemory ,然后在結(jié)束 session discard 這個(gè) WorkingMemory (產(chǎn)生一個(gè) WorkingMemory 是一個(gè)廉價(jià)的操作)。另一種形式,就是在一個(gè)相當(dāng)長的時(shí)間中(例如一個(gè) conversation ),保持一個(gè) WorkingMemory ,并且對于新的 facts 保持持續(xù)的更新。當(dāng)你希望 dispose 一個(gè) WorkingMemory 的時(shí)候,最好的實(shí)踐就是調(diào)用 dispose() 方法,此時(shí) RuleBase 中對它的引用將會(huì)被移除(盡管這是一個(gè)弱引用)。不管怎樣最后它將會(huì)被當(dāng)成垃圾收集掉。術(shù)語 WorkingMemory Actions 代表了對 WorkingMemory assertions , retractions modifications

          4.1 Facts

          Facts 是從你的應(yīng)用中,被 assert 進(jìn) WorkingMemory 中的對象( beans )。 Facts 是規(guī)則可以訪問的任意的 java 對象。規(guī)則引擎中的 facts 并不是“ clone facts ,它只是持有到你的應(yīng)用中數(shù)據(jù)的引用。 Facts 是你的應(yīng)用數(shù)據(jù)。 String 和其他沒有 getter setter 的類不是有效的 Fact 。這樣的類不能使用域約束( Field Constraints ),因?yàn)槭褂糜蚣s束要依靠 JavaBean 標(biāo)準(zhǔn)的 getter setter 來同對象交互。

          4.2 Assertion

          “Assertion” 是將 facts 告訴 WorkingMemory 的動(dòng)作,例如 WorkingMemory.assertObject (yourObject) 。當(dāng)你 assert 一個(gè) fact ,它將被檢查是否匹配規(guī)則。這意味著所有的匹配工作將會(huì)在 assert 的過程中完成。盡管如此,當(dāng)你完成 assert facts 之后,你還要調(diào)用“ fireAllRules() ”方法來執(zhí)行規(guī)則。

          當(dāng)一個(gè)對象被 assert 后,會(huì)返回一個(gè) FactHandle 。這個(gè) FactHandle 是一個(gè)代表在 Working Memory 中你的 asserted Object 的令牌( token )。當(dāng)你希望 retract 或者 modify 一個(gè)對象的時(shí)候,這個(gè)令牌讓你用來同 WorkingMemory 進(jìn)行交互。

          Cheese?stilton? = ? new ?Cheese( " stilton " );
          FactHandle?stiltonHandle?
          = ?workingMemory.assertObject(?stilton?);

          WorkingMeomry 有兩種 assertion 模式: Equality Identity (默認(rèn)是 Identity )。

          Identity 模式下 WorkingMemory 使用一個(gè) IdentityHashMap 來存儲(chǔ)所有的 asserted Objects 。這個(gè)模式下,當(dāng) asserted Object 是同一個(gè)實(shí)例時(shí),它返回同一個(gè) FactHandle

          Equality 模式下 WorkingMemory 使用一個(gè) HashMap 來存儲(chǔ)所有的 asserted Objects 。這個(gè)模式下,當(dāng) asserted Object 相等時(shí),它返回同一個(gè) FactHandle 。

          WorkingMemory.assertObject(yourObjcet) 只是進(jìn)行 assertion 的一種 regular 方法,還存在有一種稱為 logical assertion 的動(dòng)作)。

          4.3 Retraction

          基本上就是 assert 的逆操作。當(dāng)你 retract 一個(gè) fact , WorkingMemory 將不再跟蹤那個(gè) fact 。任何被 activated 并依賴那個(gè) fact 的規(guī)則將被取消。注意:完全有可能存在某條規(guī)則是依賴于一個(gè) fact 的“不存在”( non existence )。在這種情況下, retract 一個(gè) fact 將導(dǎo)致一條規(guī)則被激活。對一個(gè) Fact 進(jìn)行 Retraction ,必須用 assert 時(shí)返回的那個(gè) FactHandle 做為參數(shù)。

          Cheese?stilton? = ? new ?Cheese( " stilton " );
          FactHandle?stiltonHandle?
          = ?workingMemory.assertObject(?stilton?);
          .
          workingMemory.retractObject(?stiltonHandle?);

          4.4 Modification

          當(dāng)一個(gè) Fact 被修改了,會(huì)通知規(guī)則引擎進(jìn)行重新處理。在規(guī)則引擎內(nèi)部實(shí)際上是對舊的 Fact 進(jìn)行 retract ,然后對新的 Object 再進(jìn)行 assert 。要使用 modifyObject() 方法來通知 Working Memory ,被改變的 Object 并不會(huì)自己通知規(guī)則引擎。注意: modifyObject() 方法總是要把被修改的 Object 做為第二參數(shù),這就允許你把一個(gè)不可變對象替換為另一個(gè)新對象。

          Cheese?stilton? = ? new ?Cheese( " stilton " );
          FactHandle?stiltonHandle?
          = ?workingMemory.assertObject(?stilton?);
          .
          stilton.setPrice(?
          100 ?);
          workingMemory.modifyObject(?stiltonHandle,?stilton?);

          4.5 Globals

          Global 是一個(gè)能夠被傳進(jìn) WorkingMemory 但不需要 assert 的命名對象。大多數(shù)這些對象被用來作為靜態(tài)信息或服務(wù)。這些服務(wù)被用在一條規(guī)則的 RHS ,或者可能是從規(guī)則引擎返回對象的一種方法。

          List?list? = ? new ?ArrayList();
          workingMemory.setGlobal(
          " list " ,?list);

          setGlobal() 方法傳進(jìn)去的命名對象必須同 RuleBase 中所定義的具有相同的類型(就是要同你的規(guī)則文件中用 Global 關(guān)鍵字所定義的類型相同),否則會(huì)拋出一個(gè) RuntimeException 。如果一條規(guī)則在你 setGlobal 之前調(diào)用了定義的 Global ,會(huì)拋出一個(gè) NullPointerException 。

          4.6 Property Change Listener

          如果你的 fact 對象是 JavaBean ,你可以為它們實(shí)現(xiàn)一個(gè) property change listener ,然后把它告訴規(guī)則引擎。這意味著,當(dāng)一個(gè) fact 改變時(shí),規(guī)則引擎將會(huì)自動(dòng)知道,并進(jìn)行響應(yīng)的動(dòng)作(你不需要調(diào)用 modifyObject() 方法來通知 WorkingMemory )。 Proxy libraries 將會(huì)幫助實(shí)現(xiàn)這一切。要讓 Property Change Listener 生效,還要將 fact 設(shè)置為動(dòng)態(tài)( dynamic )模式,通過將 true 做為 assertObject() 方法的第二個(gè)參數(shù)來實(shí)現(xiàn):

          Cheese?stilton? = ? new ?Cheese( " stilton " );
          FactHandle?stiltonHandle?
          = ?workingMemory.assertObject(?stilton,? true ?);?? // specifies t hat?this?is?a?dynamic?fact

          然后要在 JavaBean 中加入一個(gè) PropertyChangeSupport 實(shí)例,和兩個(gè)方法: addPropertyChangeListener() removePropertyChangeListener() 。最后要在 JavaBean setter 方法中通知 PropertyChangeSupport 所發(fā)生的變化。示例代碼如下:

          private ? final ?PropertyChangeSupport?changes? = ? new ?PropertyChangeSupport(? this ?);

          public ? void ?addPropertyChangeListener( final ?PropertyChangeListener?l)?{
          ????
          this .changes.addPropertyChangeListener(?l?);
          }

          public ? void ?removePropertyChangeListener( final ?PropertyChangeListener?l)?{
          ????
          this .changes.removePropertyChangeListener(?l?);
          }

          public ? void ?setState( final ?String?newState)?{
          ????String?oldState?
          = ? this .state;
          ????
          this .state? = ?newState;
          this .changes.firePropertyChange(? " state " ,?oldState,?newState?);


          5. Agenda:


          Figure 5.1 . Agenda

          Agenda RETE 的一個(gè)特點(diǎn)。在一個(gè) WorkingMemory Action 發(fā)生時(shí),可能會(huì)有多條規(guī)則發(fā)生完全匹配。當(dāng)一條規(guī)則完全匹配的時(shí)候,一個(gè) Activation 就被創(chuàng)建(引用了這條規(guī)則和與其匹配的 facts ),然后放進(jìn) Agenda 中。 Agenda 通過使用沖突解決策略( Conflict Resolution Strategy )來安排這些 Activations 的執(zhí)行。

          引擎工作在一個(gè)“ 2 階段”模式下:

          <!--[if !supportLists]--> 1)? <!--[endif]--> WorkingMemory Actions assert新的facts,修改存在的factsretract facts都是WorkingMemory Actions。通過在應(yīng)用程序中調(diào)用fireAllRules()方法,會(huì)使引擎轉(zhuǎn)換到Agenda Evaluatioin階段。

          <!--[if !supportLists]--> 2)? <!--[endif]--> Agenda Evaluation :嘗試選擇一條規(guī)則進(jìn)行激發(fā)(fire)。如果規(guī)則沒有找到就退出,否則它就嘗試激發(fā)這條規(guī)則,然后轉(zhuǎn)換到WorkingMemory Actions階段,直到Agenda中為空。

          這個(gè)過程一直重復(fù),直到 Agenda 是空的,此時(shí)控制權(quán)就回到應(yīng)用程序中。。當(dāng) WorkingMemory Actions 發(fā)生時(shí),沒有規(guī)則正在被激發(fā)。

          下圖說明了這個(gè)循環(huán)的過程:


          Figure? 5.2 .?Two Phase Execution

          5 1 Conflict Resultion

          當(dāng)有多條 rules agenda 中,就需要解決沖突。當(dāng)激發(fā)一條規(guī)則時(shí),會(huì)對 WorkingMemory 產(chǎn)生副作用。規(guī)則引擎需要知道規(guī)則要以什么順序來激發(fā)(例如,激發(fā) rule A 可能會(huì)引起 rule B 被從 agenda 中移除。)

          Drools 采取的沖突解決策略有 2 種,按照優(yōu)先級排列如下: Salience , LIFO (后進(jìn)先出)。最易懂的策略是“ Salience ”,即優(yōu)先級, user 可以為某個(gè) rule 指定一個(gè)高一點(diǎn)的優(yōu)先級(通過附給它一個(gè)比較大的數(shù)字)。高 Salience rule 將會(huì)被優(yōu)先激發(fā)。

          5 2 Agenda Groups

          Agenda Groups 是劃分 Agenda rules (其實(shí)是“ activations ”)的一種方法。在任意一個(gè)時(shí)刻,只有一個(gè) group 擁有“ focus ”,這意味著只有在那個(gè) group 中的 activations 才是有效的。

          Agenda Groups 是在 grouped rules 之間創(chuàng)建一個(gè)“流”( flow )的簡便的方法。你可以在規(guī)則引擎中,或是用 API 來切換具有焦點(diǎn)的組。如果你的規(guī)則有很明確的多“階段”( phases )或多“序列”( sequences )的處理,可以考慮用 Agenda Groups 來達(dá)到這個(gè)目的。

          每次調(diào)用 setFocus() 方法的時(shí)候,那個(gè) Agenda Group 就會(huì)被壓入一個(gè)堆棧,當(dāng)這個(gè)有焦點(diǎn)的組為空時(shí),它就會(huì)被彈出,然后下一個(gè)組就會(huì)被執(zhí)行。一個(gè) Agenda Group 可以出現(xiàn)在堆棧的多個(gè)位置。默認(rèn)的 Agenda Group 是“ MAIN ”,所有沒有被指定 Agenda Group Activations 都被放到那個(gè)組中,這個(gè)組總是被放在堆棧的第一個(gè)組,并默認(rèn)給予焦點(diǎn)。

          5 3? Agenda Filters


          Figure 5.3.?Agenda Filter

          Filter 必須實(shí)現(xiàn) AgendaFilter 接口,用來允許或禁止一個(gè) activation 能夠被激發(fā)。 Drools 提供了下面幾種方便的默認(rèn)實(shí)現(xiàn):

          <!--[if !supportLists]--> ·???????? <!--[endif]--> RuleNameEndWithAgendaFilter

          <!--[if !supportLists]--> ·???????? <!--[endif]--> RuleNameEqualsAgendaFilter

          <!--[if !supportLists]--> ·???????? <!--[endif]--> RuleNameStartsWithAgendaFilter

          要使用一個(gè) filter 就要在調(diào)用 fireAllRules() 方法的時(shí)候指定它。下面的例子將對所有名字以“ Test ”結(jié)尾的規(guī)則進(jìn)行過濾:

          workingMemory.fireAllRules(? new ?RuleNameEndsWithAgendaFilter(? " Test " ?)?);

          6.事件模型( Event Model

          Event 包里提供了規(guī)則引擎的事件機(jī)制,包括規(guī)則激發(fā),對象被 asserted 等等。你可以使用事件機(jī)制來進(jìn)行 AOP 編程。

          有兩種類型的 Event Listener WorkingMemoryEventListener AgendaEventListener 。


          Figure 6.1.?WorkingMemoryEventListener


          Figure 6.2? AgendaEventListener

          對兩個(gè) EventListener 接口都提供了默認(rèn)實(shí)現(xiàn),但在方法中并沒有做任何事。你可以繼承這兩個(gè)默認(rèn)實(shí)現(xiàn)來完成你自己的實(shí)現(xiàn)- DefaultAgendaEventListener DefaultWorkingMemoryEventListener 。下面代碼說明了如何擴(kuò)展一個(gè) DefaultAgendaEventListner 并把它加到 WorkingMemory 中,例子中只完成了 afterActivationFired() 方法:

          workingMemory.addEventListener(? new ?DefaultAgendaEventListener()?{????????????????????????????
          ???
          public ? void ?afterActivationFired(AfterActivationFiredEvent?event)?{
          ???????
          super .afterActivationFired(?event?);
          ???????System.out.println(?event?);
          ???}
          ???
          });

          Drools 也提供了 DebugWorkingMemoryEventListener DebugAgendaEventListener 兩個(gè)實(shí)現(xiàn)類,在這兩個(gè)類的方法中實(shí)現(xiàn)了 debug 信息的輸出:

          workingMemory.addEventListener(? new ?DebugWorkingMemoryEventListener()?);


          posted on 2006-12-03 09:54 BPM 閱讀(684) 評論(0)  編輯  收藏 所屬分類: 規(guī)則引擎

          主站蜘蛛池模板: 保靖县| 台中县| 巫溪县| 中卫市| 普兰县| 泗洪县| 南岸区| 五寨县| 原平市| 牡丹江市| 双辽市| 宁城县| 富宁县| 长寿区| 林州市| 上栗县| 肃北| 民乐县| 旬邑县| 上犹县| 石柱| 乌拉特前旗| 宜宾县| 左权县| 茌平县| 岳普湖县| 建阳市| 南华县| 加查县| 突泉县| 湘阴县| 巫溪县| 西充县| 石泉县| 隆德县| 凤山市| 玉溪市| 织金县| 长垣县| 卓资县| 贡觉县|