不想寫大量 if 判斷?試試用規則執行器優化,就很絲滑!

近日在公司領到一個小需求,需要對之前已有的試用用戶申請規則進行拓展。我們的場景大概如下所示:

if?(是否海外用戶)?{return?false;
}if?(刷單用戶)?{return?false;
}if?(未付費用戶?&&?不再服務時段)?{return?false
}if?(轉介紹用戶?||?付費用戶?||?內推用戶)?{return?true;
}

按照上述的條件我們可以得出的結論是:

  • 咱們的的主要流程主要是基于 and 或者 or 的關系。

  • 如果有一個不匹配的話,其實咱們后續的流程是不用執行的,就是需要具備一個短路的功能。

  • 對于目前的現狀來說,我如果在原有的基礎上來改,只要稍微注意一下解決需求不是很大的問題,但是說后面可維護性非常差。

后面進過權衡過后,我還是決定將這個部分進行重構一下。

2規則執行器

針對這個需求,我首先梳理了一下咱們規則執行器大概的設計, 然后我設計了一個 V1 版本和大家一起分享一下,如果大家也有這樣的 case 可以給我分享留言,下面部分主要是設計和實現的流程和 code.

規則執行器的設計

圖片

對于規則的抽象并實現規則

//?業務數據
@Data
public?class?RuleDto?{private?String?address;private?int?age;
}//?規則抽象
public?interface?BaseRule?{boolean?execute(RuleDto?dto);
}//?規則模板
public?abstract?class?AbstractRule?implements?BaseRule?{protected?<T>?T?convert(RuleDto?dto)?{return?(T)?dto;}@Overridepublic?boolean?execute(RuleDto?dto)?{return?executeRule(convert(dto));}protected?<T>?boolean?executeRule(T?t)?{return?true;}
}//?具體規則-?例子1
public?class?AddressRule?extends?AbstractRule?{@Overridepublic?boolean?execute(RuleDto?dto)?{System.out.println("AddressRule?invoke!");if?(dto.getAddress().startsWith(MATCH_ADDRESS_START))?{return?true;}return?false;}
}//?具體規則-?例子2
public?class?NationalityRule?extends?AbstractRule?{@Overrideprotected?<T>?T?convert(RuleDto?dto)?{NationalityRuleDto?nationalityRuleDto?=?new?NationalityRuleDto();if?(dto.getAddress().startsWith(MATCH_ADDRESS_START))?{nationalityRuleDto.setNationality(MATCH_NATIONALITY_START);}return?(T)?nationalityRuleDto;}@Overrideprotected?<T>?boolean?executeRule(T?t)?{System.out.println("NationalityRule?invoke!");NationalityRuleDto?nationalityRuleDto?=?(NationalityRuleDto)?t;if?(nationalityRuleDto.getNationality().startsWith(MATCH_NATIONALITY_START))?{return?true;}return?false;}
}//?常量定義
public?class?RuleConstant?{public?static?final?String?MATCH_ADDRESS_START=?"北京";public?static?final?String?MATCH_NATIONALITY_START=?"中國";
}

執行器構建

public?class?RuleService?{private?Map<Integer,?List<BaseRule>>?hashMap?=?new?HashMap<>();private?static?final?int?AND?=?1;private?static?final?int?OR?=?0;public?static?RuleService?create()?{return?new?RuleService();}public?RuleService?and(List<BaseRule>?ruleList)?{hashMap.put(AND,?ruleList);return?this;}public?RuleService?or(List<BaseRule>?ruleList)?{hashMap.put(OR,?ruleList);return?this;}public?boolean?execute(RuleDto?dto)?{for?(Map.Entry<Integer,?List<BaseRule>>?item?:?hashMap.entrySet())?{List<BaseRule>?ruleList?=?item.getValue();switch?(item.getKey())?{case?AND://?如果是?and?關系,同步執行System.out.println("execute?key?=?"?+?1);if?(!and(dto,?ruleList))?{return?false;}break;case?OR://?如果是?or?關系,并行執行System.out.println("execute?key?=?"?+?0);if?(!or(dto,?ruleList))?{return?false;}break;default:break;}}return?true;}private?boolean?and(RuleDto?dto,?List<BaseRule>?ruleList)?{for?(BaseRule?rule?:?ruleList)?{boolean?execute?=?rule.execute(dto);if?(!execute)?{//?and?關系匹配失敗一次,返回?falsereturn?false;}}//?and?關系全部匹配成功,返回?truereturn?true;}private?boolean?or(RuleDto?dto,?List<BaseRule>?ruleList)?{for?(BaseRule?rule?:?ruleList)?{boolean?execute?=?rule.execute(dto);if?(execute)?{//?or?關系匹配到一個就返回?truereturn?true;}}//?or?關系一個都匹配不到就返回?falsereturn?false;}
}

執行器的調用

public?class?RuleServiceTest?{@org.junit.Testpublic?void?execute()?{//規則執行器//優點:比較簡單,每個規則可以獨立,將規則,數據,執行器拆分出來,調用方比較規整//缺點:數據依賴公共傳輸對象 dto//1.?定義規則??init?ruleAgeRule?ageRule?=?new?AgeRule();NameRule?nameRule?=?new?NameRule();NationalityRule?nationalityRule?=?new?NationalityRule();AddressRule?addressRule?=?new?AddressRule();SubjectRule?subjectRule?=?new?SubjectRule();//2.?構造需要的數據?create?dtoRuleDto?dto?=?new?RuleDto();dto.setAge(5);dto.setName("張三");dto.setAddress("北京");dto.setSubject("數學");;//3.?通過以鏈式調用構建和執行?rule?executeboolean?ruleResult?=?RuleService.create().and(Arrays.asList(nationalityRule,?nameRule,?addressRule)).or(Arrays.asList(ageRule,?subjectRule)).execute(dto);System.out.println("this?student?rule?execute?result?:"?+?ruleResult);}
}

3總結

規則執行器的優點和缺點

優點:

比較簡單,每個規則可以獨立,將規則,數據,執行器拆分出來,調用方比較規整;

我在 Rule 模板類中定義 convert 方法做參數的轉換這樣可以能夠,為特定 rule 需要的場景數據提供拓展。

缺點:

上下 rule 有數據依賴性,如果直接修改公共傳輸對象 dto 這樣設計不是很合理,建議提前構建數據。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/212406.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/212406.shtml
英文地址,請注明出處:http://en.pswp.cn/news/212406.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

16ASM 分段和機器碼

8086CPU存儲分段管理 問題1&#xff1a;8086是16位cpu&#xff0c;最多可訪問&#xff08;尋址&#xff09;多大內存&#xff1f; 運算器一次最多處理16位的數據。地址寄存器的最大寬度為16位。訪問的最大內存為&#xff1a;216 64K 即 0000 - FFFF。 問題2&#xff1a;808…

Hadoop集群破壞試驗可靠性驗證

集群環境說明&#xff1a; 準備5臺服務器&#xff0c;hadoop1、hadoop2、hadoop3、hadoop4、hadoop5&#xff1b; 分別部署5個節點的zookeeper集群、hadoop集群、hbase集群 本次對于Hadoop集群測試主要分為五個方面&#xff1a; 手動進行datanode節點刪除&#xff1a;&#…

typedef 與#define 的區別

typedef 與#define 的區別 typedef &#xff1a; 給一個已經存在的數據類型&#xff08;注意&#xff1a;是類型不是變量&#xff09;取一個別名&#xff0c;而非定義一個新的數據類型 #define宏定義&#xff1a; #define宏定義&#xff1a;在預編譯時直接進行簡單的文本替換 舉…

WIFI直連(Wi-Fi P2P)

一、概述 Wifi peer-to-peer&#xff08;也稱Wifi-Direct&#xff09;是Wifi聯盟推出的一項基于原來WIfi技術的可以讓設備與設備間直接連接的技術&#xff0c;使用戶不需要借助局域網或者AP&#xff08;Access Point&#xff09;就可以進行一對一或一對多通信。這種技術的應用…

計算機畢業設計 SpringBoot的樂樂農產品銷售系統 Javaweb項目 Java實戰項目 前后端分離 文檔報告 代碼講解 安裝調試

&#x1f34a;作者&#xff1a;計算機編程-吉哥 &#x1f34a;簡介&#xff1a;專業從事JavaWeb程序開發&#xff0c;微信小程序開發&#xff0c;定制化項目、 源碼、代碼講解、文檔撰寫、ppt制作。做自己喜歡的事&#xff0c;生活就是快樂的。 &#x1f34a;心愿&#xff1a;點…

Xmanager

什么是 XManager Xmanager 是市場上領先的 PC X 服務器&#xff0c;可將X應用程序的強大功能帶入 Windows 環境。 提供了強大的會話管理控制臺&#xff0c;易于使用的 X 應用程序啟動器&#xff0c;X 服務器配置文件管理工具&#xff0c;SSH 模塊和高性能 PC X 服務器。 Xman…

javaScript(六):DOM操作

文章目錄 1、DOM介紹2、DOM&#xff1a;獲取Element對象3、DOM&#xff1a;事件監聽3.1、事件介紹3.2、常見事件3.3、設置事件的兩種方式3.4、事件案例 1、DOM介紹 概念 Document Object Model &#xff0c;文檔對象模型 將標記語言的各個組成部分封裝為對應的對象&#xff1a…

Realme X7 Pro Root 刷機教程

Realme X7 Pro 刷機教程 Just For Fun&#xff0c;最近倒騰了下Realme X7 Pro 刷root。此博客為個人記錄刷機過程&#xff0c;如有機友跟隨本教程操作&#xff0c;請謹慎操作&#xff01;&#xff01;&#xff01; 以下教程真針對Realme X7 Pro&#xff0c;其他版本方法未知&…

springboot(ssm高校競賽管理系統 在線競賽平臺 Java系統

springboot(ssm高校競賽管理系統 在線競賽平臺 Java系統 開發語言&#xff1a;Java 框架&#xff1a;ssm/springboot vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服務器&#xff1a;tomcat 數據庫&#xff1a;mysql 5.7&#xff08;或8.0&#xff09; 數…

qt 模型視圖結構

在Qt中&#xff0c;Model、View和Delegate三者之間的關系如下&#xff1a; Model&#xff08;模型&#xff09;&#xff1a;Model是數據的抽象表示&#xff0c;它提供了一種結構化的方式來存儲和管理數據。Model負責維護數據的狀態&#xff0c;并提供接口供其他組件&#xff08…

【Flutter】vs2022上開發flutter

在vs上開發flutter&#xff0c;結果擴展倉庫上沒辦法找到Dart&#xff0c;Flutter。 在 這 搜索Dart時也無法找到插件。 最后發現是安裝工具出錯了 安裝了 開發需要的是

挖漏洞之文件上傳

&#xff08;一&#xff09;漏洞原理 文件上傳漏洞是指由于程序員在對用戶文件上傳部分的控制不足或者處理缺陷&#xff0c;而導致的用戶可以越過其本身權限向服務器上上傳可執行的動態腳本文件。這里上傳的文件可以是木馬&#xff0c;病毒&#xff0c;惡意腳本或者WebShell等。…

從線性回歸到神經網絡

目錄 一、線性回歸關鍵思想 1、線性模型 2、基礎優化算法 二、線性回歸的從零開始實現 1、生成數據集 2、讀取數據集 3、初始化模型參數 4、定義模型 5、定義損失函數 6、定義優化算法 7、訓練 三、線性回歸的簡潔實現 1、生成數據集 2、讀取數據集 3、定義模型…

論文代碼閱讀:TGN模型訓練階段代碼理解

文章目錄 [toc] TGN模型訓練階段代碼理解論文信息代碼過程手繪代碼訓練過程compute_temporal_embeddingsupdate_memoryget_raw_messagesget_updated_memoryself.message_aggregator.aggregateself.memory_updater.get_updated_memoryMemoryget_embedding_moduleGraphAttentionE…

什么是W3C標準? 什么要遵循?

Hi i,m JinXiang ? 前言 ? 本篇文章主要介紹HTML5中W3C的標準&#xff0c;需要遵循的規則以及部分理論知識 &#x1f349;歡迎點贊 &#x1f44d; 收藏 ?留言評論 &#x1f4dd;私信必回喲&#x1f601; &#x1f349;博主收將持續更新學習記錄獲&#xff0c;友友們有任何問…

【AIGC】Midjourney高級進階版

Midjourney 真是越玩越上頭&#xff0c;真是給它的想象力跪了~ 研究了官方API&#xff0c;出一個進階版教程 命令 旨在介紹Midjourney在Discord頻道中的文本框中支持的指令。 1&#xff09;shorten 簡化Prompt 該指令可以將輸入的Prompt為模型可以理解的語言。模型理解語言…

Git初學入門指令

git基本指令 初始化&#xff1a; git init查看狀態&#xff1a; git status新建文件&#xff1a; touch <filename>加入暫存區&#xff1a; git add . 或者 git add -A 表示全部加入暫存區 git add <filename>單個文件加入暫存區加入倉庫&#xff1a; …

PCIe中斷總結-各個中斷的區別

1.簡介&#xff1a; PCIe中斷支持三種傳輸方式&#xff1a; ? Legacy: 也稱傳統中斷&#xff0c;Legacy PCI中斷機制,每個PCI設備最多支持四個中斷信號(邊帶信號:INTA# INTB# INTC# INTD#) ? MSI(Message Signaled Interrupt): Post Memory Write,只支持32個中斷向量 ? MSI…

力扣labuladong一刷day35天

力扣labuladong一刷day35天 文章目錄 力扣labuladong一刷day35天一、98. 驗證二叉搜索樹二、700. 二叉搜索樹中的搜索三、701. 二叉搜索樹中的插入操作四、450. 刪除二叉搜索樹中的節點 一、98. 驗證二叉搜索樹 題目鏈接&#xff1a;https://leetcode.cn/problems/validate-bi…

【Linux】如何對文本文件進行有條件地劃分?——cut命令

cut 命令可以根據一個指定的標記&#xff08;默認是 tab&#xff09;來為文本劃分列&#xff0c;然后將此列顯示。 例如想要顯示 passwd 文件的第一列可以使用以下命令&#xff1a;cut –f 1 –d : /etc/passwd cut&#xff1a;用于從文件的每一行中提取部分內容的命令。-f 1&…