WorkingMemory
是運行時規則引擎的主要類。它保持了所有被
asserted
進
WorkingMemory
的數據的引用,直到取消(
retracted
)。
WorkingMemory
是有狀態對象。它們的生命周期可長可短。如果從一個短生命周期的角度來同一個引擎進行交互,意味著你可以使用
RuleBase
對象來為每個
session
產生一個新的
WorkingMemory
,然后在結束
session
后
discard
這個
WorkingMemory
(產生一個
WorkingMemory
是一個廉價的操作)。另一種形式,就是在一個相當長的時間中(例如一個
conversation
),保持一個
WorkingMemory
,并且對于新的
facts
保持持續的更新。當你希望
dispose
一個
WorkingMemory
的時候,最好的實踐就是調用
dispose()
方法,此時
RuleBase
中對它的引用將會被移除(盡管這是一個弱引用)。不管怎樣最后它將會被當成垃圾收集掉。術語
WorkingMemory Actions
代表了對
WorkingMemory
的
assertions
,
retractions
和
modifications
。
4.1 Facts
Facts
是從你的應用中,被
assert
進
WorkingMemory
中的對象(
beans
)。
Facts
是規則可以訪問的任意的
java
對象。規則引擎中的
facts
并不是“
clone
”
facts
,它只是持有到你的應用中數據的引用。
Facts
是你的應用數據。
String
和其他沒有
getter
和
setter
的類不是有效的
Fact
。這樣的類不能使用域約束(
Field Constraints
),因為使用域約束要依靠
JavaBean
標準的
getter
和
setter
來同對象交互。
4.2 Assertion
“Assertion”
是將
facts
告訴
WorkingMemory
的動作,例如
WorkingMemory.assertObject
(yourObject)
。當你
assert
一個
fact
,它將被檢查是否匹配規則。這意味著所有的匹配工作將會在
assert
的過程中完成。盡管如此,當你完成
assert facts
之后,你還要調用“
fireAllRules()
”方法來執行規則。
當一個對象被
assert
后,會返回一個
FactHandle
。這個
FactHandle
是一個代表在
Working Memory
中你的
asserted Object
的令牌(
token
)。當你希望
retract
或者
modify
一個對象的時候,這個令牌讓你用來同
WorkingMemory
進行交互。
Cheese?stilton?
=
?
new
?Cheese(
"
stilton
"
);
FactHandle?stiltonHandle?
=
?workingMemory.assertObject(?stilton?);
WorkingMeomry
有兩種
assertion
模式:
Equality
和
Identity
(默認是
Identity
)。
Identity
模式下
WorkingMemory
使用一個
IdentityHashMap
來存儲所有的
asserted Objects
。這個模式下,當
asserted
的
Object
是同一個實例時,它返回同一個
FactHandle
。
Equality
模式下
WorkingMemory
使用一個
HashMap
來存儲所有的
asserted Objects
。這個模式下,當
asserted
的
Object
相等時,它返回同一個
FactHandle
。
(
WorkingMemory.assertObject(yourObjcet)
只是進行
assertion
的一種
regular
方法,還存在有一種稱為
logical assertion
的動作)。
4.3 Retraction
基本上就是
assert
的逆操作。當你
retract
一個
fact
,
WorkingMemory
將不再跟蹤那個
fact
。任何被
activated
并依賴那個
fact
的規則將被取消。注意:完全有可能存在某條規則是依賴于一個
fact
的“不存在”(
non existence
)。在這種情況下,
retract
一個
fact
將導致一條規則被激活。對一個
Fact
進行
Retraction
,必須用
assert
時返回的那個
FactHandle
做為參數。
Cheese?stilton?
=
?
new
?Cheese(
"
stilton
"
);
FactHandle?stiltonHandle?
=
?workingMemory.assertObject(?stilton?);
.
workingMemory.retractObject(?stiltonHandle?);
4.4 Modification
當一個
Fact
被修改了,會通知規則引擎進行重新處理。在規則引擎內部實際上是對舊的
Fact
進行
retract
,然后對新的
Object
再進行
assert
。要使用
modifyObject()
方法來通知
Working Memory
,被改變的
Object
并不會自己通知規則引擎。注意:
modifyObject()
方法總是要把被修改的
Object
做為第二參數,這就允許你把一個不可變對象替換為另一個新對象。
Cheese?stilton?
=
?
new
?Cheese(
"
stilton
"
);
FactHandle?stiltonHandle?
=
?workingMemory.assertObject(?stilton?);
.
stilton.setPrice(?
100
?);
workingMemory.modifyObject(?stiltonHandle,?stilton?);
4.5 Globals
Global
是一個能夠被傳進
WorkingMemory
但不需要
assert
的命名對象。大多數這些對象被用來作為靜態信息或服務。這些服務被用在一條規則的
RHS
,或者可能是從規則引擎返回對象的一種方法。
List?list?
=
?
new
?ArrayList();
workingMemory.setGlobal(
"
list
"
,?list);
setGlobal()
方法傳進去的命名對象必須同
RuleBase
中所定義的具有相同的類型(就是要同你的規則文件中用
Global
關鍵字所定義的類型相同),否則會拋出一個
RuntimeException
。如果一條規則在你
setGlobal
之前調用了定義的
Global
,會拋出一個
NullPointerException
。
4.6 Property Change Listener
如果你的
fact
對象是
JavaBean
,你可以為它們實現一個
property change listener
,然后把它告訴規則引擎。這意味著,當一個
fact
改變時,規則引擎將會自動知道,并進行響應的動作(你不需要調用
modifyObject()
方法來通知
WorkingMemory
)。
Proxy libraries
將會幫助實現這一切。要讓
Property Change Listener
生效,還要將
fact
設置為動態(
dynamic
)模式,通過將
true
做為
assertObject()
方法的第二個參數來實現:
Cheese?stilton?
=
?
new
?Cheese(
"
stilton
"
);
FactHandle?stiltonHandle?
=
?workingMemory.assertObject(?stilton,?
true
?);??
//
specifies
t
hat?this?is?a?dynamic?fact
然后要在
JavaBean
中加入一個
PropertyChangeSupport
實例,和兩個方法:
addPropertyChangeListener()
和
removePropertyChangeListener()
。最后要在
JavaBean
的
setter
方法中通知
PropertyChangeSupport
所發生的變化。示例代碼如下:
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
的一個特點。在一個
WorkingMemory
Action
發生時,可能會有多條規則發生完全匹配。當一條規則完全匹配的時候,一個
Activation
就被創建(引用了這條規則和與其匹配的
facts
),然后放進
Agenda
中。
Agenda
通過使用沖突解決策略(
Conflict Resolution
Strategy
)來安排這些
Activations
的執行。
引擎工作在一個“
2
階段”模式下:
1)?
WorkingMemory Actions
:
assert
新的
facts
,修改存在的
facts
和
retract facts
都是
WorkingMemory Actions
。通過在應用程序中調用
fireAllRules()
方法,會使引擎轉換到
Agenda Evaluatioin
階段。
2)?
Agenda Evaluation
:嘗試選擇一條規則進行激發(
fire
)。如果規則沒有找到就退出,否則它就嘗試激發這條規則,然后轉換到
WorkingMemory Actions
階段,直到
Agenda
中為空。
這個過程一直重復,直到
Agenda
是空的,此時控制權就回到應用程序中。。當
WorkingMemory
Actions
發生時,沒有規則正在被激發。
下圖說明了這個循環的過程:
Figure? 5.2 .?Two Phase Execution
5
.
1 Conflict
Resultion
當有多條
rules
在
agenda
中,就需要解決沖突。當激發一條規則時,會對
WorkingMemory
產生副作用。規則引擎需要知道規則要以什么順序來激發(例如,激發
rule
A
可能會引起
rule B
被從
agenda
中移除。)
Drools
采取的沖突解決策略有
2
種,按照優先級排列如下:
Salience
,
LIFO
(后進先出)。最易懂的策略是“
Salience
”,即優先級,
user
可以為某個
rule
指定一個高一點的優先級(通過附給它一個比較大的數字)。高
Salience
的
rule
將會被優先激發。
5
.
2 Agenda Groups
Agenda Groups
是劃分
Agenda
中
rules
(其實是“
activations
”)的一種方法。在任意一個時刻,只有一個
group
擁有“
focus
”,這意味著只有在那個
group
中的
activations
才是有效的。
Agenda Groups
是在
grouped rules
之間創建一個“流”(
flow
)的簡便的方法。你可以在規則引擎中,或是用
API
來切換具有焦點的組。如果你的規則有很明確的多“階段”(
phases
)或多“序列”(
sequences
)的處理,可以考慮用
Agenda Groups
來達到這個目的。
每次調用
setFocus()
方法的時候,那個
Agenda Group
就會被壓入一個堆棧,當這個有焦點的組為空時,它就會被彈出,然后下一個組就會被執行。一個
Agenda Group
可以出現在堆棧的多個位置。默認的
Agenda Group
是“
MAIN
”,所有沒有被指定
Agenda
Group
的
Activations
都被放到那個組中,這個組總是被放在堆棧的第一個組,并默認給予焦點。
5
.
3? Agenda Filters
Figure 5.3.?Agenda Filter
Filter
必須實現
AgendaFilter
接口,用來允許或禁止一個
activation
能夠被激發。
Drools
提供了下面幾種方便的默認實現:
·????????
RuleNameEndWithAgendaFilter
·????????
RuleNameEqualsAgendaFilter
·????????
RuleNameStartsWithAgendaFilter
要使用一個
filter
就要在調用
fireAllRules()
方法的時候指定它。下面的例子將對所有名字以“
Test
”結尾的規則進行過濾:
workingMemory.fireAllRules(?
new
?RuleNameEndsWithAgendaFilter(?
"
Test
"
?)?);
6.事件模型(
Event Model
)
Event
包里提供了規則引擎的事件機制,包括規則激發,對象被
asserted
等等。你可以使用事件機制來進行
AOP
編程。
有兩種類型的
Event
Listener
:
WorkingMemoryEventListener
和
AgendaEventListener
。
Figure 6.1.?WorkingMemoryEventListener
Figure 6.2? AgendaEventListener
對兩個
EventListener
接口都提供了默認實現,但在方法中并沒有做任何事。你可以繼承這兩個默認實現來完成你自己的實現-
DefaultAgendaEventListener
和
DefaultWorkingMemoryEventListener
。下面代碼說明了如何擴展一個
DefaultAgendaEventListner
并把它加到
WorkingMemory
中,例子中只完成了
afterActivationFired()
方法:
workingMemory.addEventListener(?
new
?DefaultAgendaEventListener()?{????????????????????????????
???
public
?
void
?afterActivationFired(AfterActivationFiredEvent?event)?{
???????
super
.afterActivationFired(?event?);
???????System.out.println(?event?);
???}
???
});
Drools
也提供了
DebugWorkingMemoryEventListener
和
DebugAgendaEventListener
兩個實現類,在這兩個類的方法中實現了
debug
信息的輸出:
workingMemory.addEventListener(?
new
?DebugWorkingMemoryEventListener()?);