java?設計模式從風控鏈理解責任鏈模式
前言
責任鏈是一種行為型模式。顧名思義,由多個有不同處理能力節(jié)點組成的一條執(zhí)行鏈。當一個事件進來時,會判斷當前節(jié)點是否有處理的能力,反之轉入下一個節(jié)點進行處理??梢詮闹Ц兜娘L控鏈這個場景,深入的理解責任鏈模式。
定義
責任鏈模式:包含了一些命令和一系列的處理對象。每一個處理對象決定了它能處理哪些命令對象,它也知道如何將它不能處理的命令對象傳遞給該鏈中的下一個處理對象。
如何理解
信用卡套現(xiàn),花唄套現(xiàn),白條套現(xiàn),類似的名詞對于我們來講應該不陌生吧。在支付系統(tǒng)中會有一套風控系統(tǒng),來避免發(fā)生類似的事情出現(xiàn)。而風控系統(tǒng)就是責任鏈模式的一種應用。
比如說給xxx商戶配置的風控規(guī)則是:
TOP | 信用卡 | 花唄 | 白條 |
---|---|---|---|
木屋燒烤 | 500/日 | 300/日 | 300/日 |
當用戶向商家付款時,會根據(jù)不同的支付方式,來判斷是否觸發(fā)風控條件。如果達到觸發(fā)條件則不允許使用該方式支付。來避免發(fā)生信用卡套現(xiàn)類似的事情。
我們寫個簡單的風控程序來理解一下:
UML
代碼示例
RiskHandler
public abstract class RiskHandler { /** * 支付方式 */ private String payType; private RiskHandler nextHandler; public RiskHandler(String payType) { this.payType = payType; } /** * 是否能支付 * @param order 訂單 */ protected abstract boolean canPay(Order order); /** * 處理器 * @param order 訂單 * @return 返回true 或者 false */ public final boolean handler(Order order){ if(order.getPayType().equals(this.payType)){ return this.canPay(order); }else { if (this.nextHandler != null){ return this.nextHandler.handler(order); }else{ throw new IllegalArgumentException("支付方式有誤"); } } } public void setNextHandler(RiskHandler handler){ this.nextHandler = handler; } }
CreditHandler
public class CreditHandler extends RiskHandler { /** * 500 限額 */ private BigDecimal limitAmount = BigDecimal.valueOf(500); public CreditHandler() { super(PayTypeEnum.CREDIT.getPayType()); } @Override protected boolean canPay(Order order) { if(order.getAmount().compareTo(limitAmount) < 0){ limitAmount = limitAmount.subtract(order.getAmount()); return true; }else { return false; } } }
HuabeiHandler
public class HuabeiHandler extends RiskHandler { /** * 300 限額 */ private BigDecimal limitAmount = BigDecimal.valueOf(300); public HuabeiHandler() { super(PayTypeEnum.HUA_BEI.getPayType()); } @Override protected boolean canPay(Order order) { if(order.getAmount().compareTo(limitAmount) < 0){ limitAmount = limitAmount.subtract(order.getAmount()); return true; }else { return false; } } }
BaiTiaoHandler
public class BaiTiaoHandler extends RiskHandler { /** * 300 限額 */ private BigDecimal limitAmount = BigDecimal.valueOf(300); public BaiTiaoHandler() { super(PayTypeEnum.BAI_TIAO.getPayType()); } @Override protected boolean canPay(Order order) { if(order.getAmount().compareTo(limitAmount) < 0){ limitAmount = limitAmount.subtract(order.getAmount()); return true; }else { return false; } } }
Order
public interface Order { /** * 獲取支付方式 * @return 支付方式 */ String getPayType(); /** * 獲取訂單金額 * @return 訂單金額 */ BigDecimal getAmount(); }
ConsumeOrder
public class ConsumeOrder implements Order { private String payType; private BigDecimal amount; public ConsumeOrder(String payType, BigDecimal amount) { this.payType = payType; this.amount = amount; } @Override public String getPayType() { return this.payType; } @Override public BigDecimal getAmount() { return this.amount; } }
PayTypeEnum
public enum PayTypeEnum { /** * 花唄 */ HUA_BEI("hua_bei"), /** * 白條 */ BAI_TIAO("bai_tiao"), /** * 信用卡 */ CREDIT("credit"), ; private String payType; PayTypeEnum(String payType) { this.payType = payType; } public String getPayType() { return payType; } }
PayRiskControlService
public class PayRiskControlService { public boolean canPay(Order order){ // 設置風控 RiskHandler creditHandler = new CreditHandler(); RiskHandler huabeiHandler = new HuabeiHandler(); RiskHandler baiTiaoHandler = new BaiTiaoHandler(); creditHandler.setNextHandler(huabeiHandler); huabeiHandler.setNextHandler(baiTiaoHandler); return creditHandler.handler(order); } }
Test
public class Test { public static void main(String[] args) { // 花唄訂單 ConsumeOrder huabeiOrder = new ConsumeOrder( PayTypeEnum.HUA_BEI.getPayType(), BigDecimal.valueOf(200) ); // 白條訂單 ConsumeOrder baitiaoOrder = new ConsumeOrder( PayTypeEnum.BAI_TIAO.getPayType(), BigDecimal.valueOf(301) ); // 加載風控系統(tǒng) PayRiskControlService riskControlService = new PayRiskControlService(); // 創(chuàng)建訂單 boolean canPayOfHuabei = riskControlService.canPay(huabeiOrder); boolean canPayOfBaitiao = riskControlService.canPay(baitiaoOrder); System.out.println("canPayOfHuabei = " + canPayOfHuabei); System.out.println("canPayOfBaitiao = " + canPayOfBaitiao); } }
測試結果
ConsumeOrder{payType='hua_bei', amount=200} canPay: true
ConsumeOrder{payType='bai_tiao', amount=301} canPay: false
優(yōu)點
- 降低耦合度,將請求和處理分開。
- 簡化了對象,是對象不需要知道鏈的結構。
- 增強給對象指派職責的靈活性,通過改變鏈內的成員或者調動他們的次序,運行動態(tài)的新增或者刪除責任。
- 增加新的處理類很方便。
缺點
- 不能保證請求一定被接收
- 系統(tǒng)性能將受到一定影響,而且在調試代碼時不太方便,可能會造成循環(huán)調用。
- 可能不容易觀察運行時的特征,有礙于除錯。
應用場景
- 有多個對象可以處理同一個請求,具體是哪個對象處理由該請求運行時刻自動確定。
- 在不明確接受者的情況下,向多個對象中的一個提交一個請求。
- 可以動態(tài)指定一組對象處理請求。
責任鏈模式的兩種情況
純的職責鏈模式
一個請求必須被某一個處理者對象所接收,且一個具體處理者對某個請求的處理只能采用以下兩種行為之一:自己處理(承擔責任),把責任推給下家處理。
不純的職責鏈模式
允許出現(xiàn)某一個具體處理者對象在承擔了請求的一部分責任后又將剩余的責任傳給下家的情況,且一個請求可以最終不被任何接收端對象所接收。比如說,多級審核,登錄安全監(jiān)測。
注意的點
鏈中節(jié)點數(shù)量需要控制,避免出現(xiàn)超長鏈的情況,一般的做法是在Handler中設置一個最大節(jié)點數(shù)量,在setNext方法中判斷是否已經(jīng)是超過其閾值,超過則不允許該鏈建立,避免無意識地破壞系統(tǒng)性能。
參考文章
- 設計模式之禪道第二版
- 責任鏈設計模式|菜鳥教程
以上就是java 設計模式從風控鏈理解責任鏈模式的詳細內容,更多關于java責任鏈模式的資料請關注腳本之家其它相關文章!
相關文章
Java Tree結構數(shù)據(jù)中查找匹配節(jié)點方式
這篇文章主要介紹了Java Tree結構數(shù)據(jù)中查找匹配節(jié)點方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09Spring MVC中處理ajax請求的跨域問題與注意事項詳解
跨域問題是我們大家在開發(fā)中會經(jīng)常遇到的一個問題,所以下面這篇文章主要給大家介紹了關于Spring MVC中處理ajax請求的跨域問題與注意事項的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧。2017-11-11SpringBoot2.0整合Shiro框架實現(xiàn)用戶權限管理的示例
這篇文章主要介紹了SpringBoot2.0整合Shiro框架實現(xiàn)用戶權限管理的示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-08-08Spring Boot實現(xiàn)圖片上傳/加水印一把梭操作實例代碼
這篇文章主要給大家介紹了關于Spring Boot實現(xiàn)圖片上傳/加水印一把梭操作的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2018-11-11Java 配置log4j日志文件路徑 (附-獲取當前類路徑的多種操作)
這篇文章主要介紹了Java 配置log4j日志文件路徑 (附-獲取當前類路徑的多種操作),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10