設計模式-責任鏈模式

前言

  你們好我是不同的科技宅,天天進步一點點,體驗不同的生活。今天給你們帶來的是責任鏈模式,責任鏈是一種行爲型模式。顧名思義,由多個有不一樣處理能力節點組成的一條執行鏈。當一個事件進來時,會判斷當前節點是否有處理的能力,反之轉入下一個節點進行處理。html

定義

  責任鏈模式:包含了一些命令和一系列的處理對象。每個處理對象決定了它能處理哪些命令對象,它也知道如何將它不能處理的命令對象傳遞給該鏈中的下一個處理對象。java

如何理解

  信用卡套現,花唄套現,白條套現,相似的名詞對於咱們來說應該不陌生吧。在支付系統中會有一套風控系統,來避免發生相似的事情出現。而風控系統就是責任鏈模式的一種應用。設計模式

好比說給xxx商戶配置的風控規則是:安全

TOP 信用卡 花唄 白條
木屋燒烤 500/日 300/日 300/日

  當用戶向商家付款時,會根據不一樣的支付方式,來判斷是否觸發風控條件。若是達到觸發條件則不容許使用該方式支付。來避免發生信用卡套現相似的事情。ide

咱們寫個簡單的風控程序來理解一下:性能

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)
        );

        // 加載風控系統
        PayRiskControlService riskControlService = new PayRiskControlService();

        // 建立訂單
        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

優勢

  • 下降耦合度,將請求和處理分開。
  • 簡化了對象,是對象不須要知道鏈的結構。
  • 加強給對象指派職責的靈活性,經過改變鏈內的成員或者調動他們的次序,運行動態的新增或者刪除責任。
  • 增長新的處理類很方便。

缺點

  • 不能保證請求必定被接收
  • 系統性能將受到必定影響,並且在調試代碼時不太方便,可能會形成循環調用。
  • 可能不容易觀察運行時的特徵,有礙於除錯。

應用場景

  • 有多個對象能夠處理同一個請求,具體是哪一個對象處理由該請求運行時刻自動肯定。
  • 在不明確接受者的狀況下,向多個對象中的一個提交一個請求。
  • 能夠動態指定一組對象處理請求。

責任鏈模式的兩種狀況

純的職責鏈模式

  一個請求必須被某一個處理者對象所接收,且一個具體處理者對某個請求的處理只能採用如下兩種行爲之一:本身處理(承擔責任),把責任推給下家處理。測試

不純的職責鏈模式

  容許出現某一個具體處理者對象在承擔了請求的一部分責任後又將剩餘的責任傳給下家的狀況,且一個請求能夠最終不被任何接收端對象所接收。好比說,多級審覈登陸安全監測this

注意的點

  鏈中節點數量須要控制,避免出現超長鏈的狀況,通常的作法是在Handler中設置一個最大節點數量,在setNext方法中判斷是否已是超過其閾值,超過則不容許該鏈創建,避免無心識地破壞系統性能。spa

參考文章

結尾

  若是以爲對你有幫助,能夠多多評論,多多點贊哦,也能夠到個人主頁看看,說不定有你喜歡的文章,也能夠隨手點個關注哦,謝謝。設計

相關文章
相關標籤/搜索