如何學習Java的規則引擎模式? - plagov
在這篇博文中,我想描述一下我是如何在為開源專案做出貢獻的同時瞭解規則引擎模式的。
在我作為測試自動化工程師的工作中,我一直在使用 Selenide。所以,當我必須完成某項任務時,我發現 Selenide 沒有解決方案來幫助我。所以,我認為這可能是一個為開源庫貢獻新功能的好機會。
問題
我遇到的問題是這樣的。Selenide庫有一個函式,可以在當前元素的HTML DOM中找到一個父節點。這個父節點是同一個HTML元素,所以它有不同的屬性,可以用來在頁面上定位它--一個標籤名、一個類名、一個屬性、一個有值的屬性。所以,我們的任務是為每個選項建立一個XPath表示式。
一個非常直接的解決方案是做一個if - else if - else語句。但有了上面提到的四個選項,這種結構就顯得太草率了。一定有一個更好、更乾淨的方法來完成這個任務。
規則引擎模式
對於這種問題,確實有一種更好的方法--規則引擎模式。這種模式的本質是將每一個if - else if - else分支分割在其規則類中。然後,主規則引擎類將持有所有的規則,並找到符合客戶要求的規則。
定義一個規則類
為了確保所有的規則類將實現相同的方法,讓我們定義一個介面,每個類將實現這個介面。
public interface AncestorRule { Optional<AncestorResult> evaluate(String selector); } |
接下來,讓我們定義第一個規則類。該類將容納if-else分支中定義的邏輯:
public class AncestorWithClassRule implements AncestorRule { @Override public Optional<AncestorResult> evaluate(String selector) { if (isCssClass(selector)) { String xpath = format( "ancestor::*[contains(concat(' ', normalize-space(@class), ' '), ' %s ')][%s]", selector.substring(1) ); return Optional.of(new AncestorResult(xpath)); } return Optional.empty(); } } |
所以,這裡是檢查給定選擇器是否符合給定條件的單一邏輯--如果它是一個CSS類。isCssClass()是一個定義在supper類中的函式(為了簡潔起見,這裡沒有顯示)。如果選擇器確實是一個CSS類,那麼它將建立一個XPath表示式,並將其作為AncestorResult的一個Optional返回,否則就是一個空Optional。
這個規則類是乾淨的、簡短的、容易理解的。它只需寫一次,不需要經常修改,除非規則的業務邏輯被更新。
我們以同樣的方式定義其他規則。如果輸入符合給定的條件,就驗證,建立並返回相應的XPath表示式。否則,就是一個空的結果。
規則結果
上面的程式碼有AncestorResult的用法。這個類的目的是包裝成功評估計算的結果。這個類看起來如下。
public class AncestorResult { private final String value; public AncestorResult(String value) { this.value = value; } public String getValue() { return value; } } |
只有一個類的欄位,我們透過建構函式來設定,用getter來訪問它。
規則引擎類
現在,讓我們最後來看看持有規則引擎邏輯的類。
public class AncestorRuleEngine { private static final List<AncestorRule> rules = Arrays.asList( new AncestorWithTagRule(), new AncestorWithClassRule(), new AncestorWithAttributeRule(), new AncestorWithAttributeAndValueRule() ); public AncestorResult process(String selector) { return rules .stream() .map(rule -> rule.evaluate(selector)) .flatMap(optional -> optional.map(Stream::of).orElseGet(Stream::empty)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("Selector does not match any rule")); } } |
在這個類中做的第一件事是一個適用於這個領域的所有規則的靜態列表。如果我們有一個新的規則--我們實現一個新的類並將其新增到這個規則列表中。
第二件事是在所有的規則中處理客戶的輸入。它對規則列表進行流式處理,評估每一條規則。規則的第一個非空的結果被返回給客戶端。否則,規則引擎將丟擲一個異常。
關於flatMap()操作的一點。之前的map()函式返回一個Optionals流。然後,flatMap()將一個空的Optionals流轉換為一個空流。否則,就轉換成非空的AncestorResults流,並將其封裝為Optional。該結構與Java 8相容,看起來很冗長。幸運的是,從Java 9開始,這可以被簡化。
規則引擎的使用
現在,當我們實現了所有的或規則,規則引擎被定義,讓我們看看如何呼叫和使用這個引擎。
public class ClientSideThatCallsTheRuleEngine { public void executeClientCode() { // some executions AncestorRuleEngine ruleEngine = new AncestorRuleEngine(); String xpath = ruleEngine.process(selector).getValue(); // other executions } } |
就這麼簡單。例項化一個規則引擎。傳入客戶的輸入並得到結果。這很乾淨,簡短,精確。我們隱藏了所有驗證輸入的低階邏輯,建立各自的結果,處理它。與帶有多個if - else分支的直截了當的方法相比。我們新增的邏輯越多,這個if - else怪物就越多。
相關文章
- 規則引擎模式 - upperdine模式
- 在Java中用規則引擎模式替代ifelse - VitaliJava模式
- Java各種規則引擎Java
- Java規則引擎 Easy RulesJava
- 規則引擎模式的.NET開源專案案例模式
- 用 Java 構建簡單的規則引擎Java
- uwegeercken/jare:Java業務規則引擎(Jare)JARJava
- 規則引擎與機器學習比較與結合機器學習
- URule規則引擎
- 開放封閉原則與規則引擎設計模式 - devgenius設計模式dev
- 如何用Go快速實現規則引擎Go
- .NET RulesEngine(規則引擎)
- j-easy/easy-rules: Java簡單的規則引擎Java
- Java中最流行的幾種業務規則引擎簡介Java
- 風控規則引擎(一):Java 動態指令碼Java指令碼
- 使用DDD規格Specification模式構建資料驅動規則引擎 - jonblankenship模式
- 架構 規則引擎 quartz架構quartz
- Drools 規則引擎應用
- Drools規則引擎簡介
- camunda快速入門(五):DMN規則引擎如何使用
- 決策表模式: 一種業務規則引擎實現方式模式
- 規則引擎在IoT的重要性?
- Drools 業務規則引擎的完整教程
- 什麼是規則引擎? - martinfowler
- Evrete 規則引擎簡介 | baeldungVR
- 規則引擎Golang指南 – Mohit KhareGolang
- 如何編寫一個簡單但強大的規則引擎? – maxant
- 規則引擎與ML模型的比較 - xLaszlo模型
- 數字化轉型中的規則引擎
- 一個規則引擎的視覺化方案視覺化
- 快速整合和使用 drools 規則引擎
- 什麼是業務規則引擎?
- 全渠道營銷規則引擎案例
- 通過規則引擎跟蹤Java執行狀態的檢測工具:BytemanJava
- java學習之道 --- 如何學習java?Java
- 基於Groovy的規則指令碼引擎實戰指令碼
- 基於 XAF Blazor 的規則引擎編輯器Blazor
- .NET 6中使用Jint的JavaScript規則引擎JavaScript