easyrule的原始碼解析

個人認為,如何是一個初學者,想要透過讀原始碼來提高自己的程式碼水平,選一個小而優美的專案來入門很重要。上來就去看spring等大型專案的原始碼,就像劉姥姥進大觀園一樣摸不到頭腦,而且會打擊自己的積極性,不利於今後的學習。easyrule就是這樣一個很簡單規則引擎,它的原始碼非常簡單,而且很整潔,裡面用了一些比較通用的設計模式,適合原始碼初學者練習如何讀原始碼。

我們從專案的結構,uml,設計模式三個方面來講解。如果想了解easyrule怎麼使用,可以移步到我的前幾篇文章。

專案結構

一共就三個包,annotation包、api包、core包。annotation包主要是定義一些註解,這些註解是定義一個rule時所需要設定的。api包主要定義的是定義基礎介面和基礎類。core包定義了主要的邏輯實現程式碼。可能是程式碼量比較少,所以作者並沒有刻意地去做分層。

開發建議:分層是一個梳理複雜專案的一個好的解決方案,但並不是一個標準。刻意地分層也會造成程式碼的複雜化。所以要具體問題具體分析,實踐出真理。

easyrule的原始碼解析

UML和設計模式

UML是觀察學習一個專案結構最有效的方式之一。各位同學在學習其他框架時也可以試著畫一下UML來分析專案的脈絡。

先上一個大圖,看似一個很簡單的專案,都有這麼複雜的結構,更別說spring了。

easyrule的原始碼解析

這個是個整體結構,看不太清,咱們分解來看。

1 api包中主要定義的是定義基礎介面和基礎類。所以根據api包中的類的關係,我們就可以把握整體的脈絡。

RulesEngine是整個規則引擎的核心,它的fire方法用來執行所有的Rules和Facts;

RulesEngineParameters是構造RulesEngine的引數;

Rules是Rule的集合,Facts是Fact的集合;

Condition和Action是規則條件和執行操作的介面定義;

RuleListener和RulesEngineListener是規則匹配的監聽器定義。

easyrule的原始碼解析

2 定義rule的方式:分為三種,一種是實現Rule介面,一種是註解方式,一種是構造器的方式。

實現Rule介面:

不用多說,定義一個類implements Rule,並實現Rule中的方法就ok了。

註解方式:

Rules在register時呼叫RuleProxy。asRule。註解方式最核心的類是RuleProxy,它利用了java的動態代理,來實現含有註解的規則類與Rule之間的轉換。動態代理是一個經典的設計模式,下節我們會講easyrule是怎麼運用的。在轉換之前要經過RuleDefinitionValidator。validateRuleDefinition對規則物件進行完整性校驗。

easyrule的原始碼解析

代理模式的定義:代理模式給某一個物件提供一個代理物件,並由代理物件控制對原物件的引用。通俗的來講代理模式就是我們生活中常見的中介。而動態代理模式:當客戶端透過Proxy的靜態方法生成動態代理類(RuleProxy)後,呼叫動態代理類對應的介面方法時,內部會呼叫其內部持有的InvocationHandler介面的例項物件的invoke方法,並得以呼叫到實際被代理實體的相應方法。

構造器的方式:

其最核心的類是RuleBuilder,它是設計模式建造者模式的一個典型。最後透過build方法構造出一個DefaultRule的預設規則。

easyrule的原始碼解析

建造者模式:指將一個複雜物件的構造與它的表示分離,使同樣的構建過程可以建立不同的表示。這個定義好像有點難懂。我們舉個例子:我們想要配一臺電腦。如果簡單點,只需要主機、顯示器、鍵盤、滑鼠就ok了;如果是玩遊戲,需要加一個大記憶體、顯示卡;如果玩攝影、看電影,需要加一個大點的硬碟;如果要經常影片通訊,就要加一個網絡卡、攝像頭等等。透過建造者模式,我們可以diy各種不同的物件。它將一個複雜的物件分解為多個簡單的物件,然後一步一步構建而成。

3 規則引擎類,上面也說了RulesEngine是整個規則引擎的核心。AbstractRulesEngine實現了RulesEngine,提供了註冊監聽器(RuleListener,RulesEngineListener)的方法;DefaultRulesEngine和InferenceRulesEngine為兩種規則引擎的具體實現。這裡用到兩種設計模式:模版模式(AbstractRulesEngine,DefaultRulesEngine,InferenceRulesEngine)和觀察者模式(RuleListener,RulesEngineListener)。

easyrule的原始碼解析

模版模式:完成一件事情,有固定的數個步驟,但是每個步驟根據物件的不同,而實現細節不同;就可以在父類AbstractRulesEngine中定義一個完成該事情的總方法,按照完成事件需要的步驟去呼叫其每個步驟的實現方法。每個步驟的具體實現,由子類(DefaultRulesEngine、InferenceRulesEngine)完成。

觀察者模式:指多個物件間存在一對多的依賴關係,當一個物件(DefaultRulesEngine)的狀態發生改變時,所有依賴於它的物件(RuleListener、RulesEngineListener)都得到通知並被自動更新。

仔細閱讀發現,作者有的地方沒有嚴格按照設計模式來寫,寫的也挺隨意的,猜測是寫到最後寫不下去了,不如流水賬寫的快。總體來講,這個程式碼還是清晰易懂的,適合小白來學習。同學們看看easyrule的原始碼中還有什麼其他的設計模式嗎?可以留言交流。