責任鏈模式是一種設計模式。在責任鏈模式里,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織和分配責任
-百度百科
寫了這么多年代碼,我一直秉承着 以無形勝有形 的風格去累代碼,我也常常的去看 《設計模式》嘗試着從里面找到一種牛B的模式來解決,解耦業務代碼!前人的經驗總是值得我們去學習的,老話說的好:“吃的鹽比你吃的飯還多”。這次剛好寫一個支付接口,經過業務分析,我想到了 23種設計模式中的 責任鏈模式。 剛好可以拿來借鑒!
業務需求
現有一個支付接口需求,能接受 多種的支付方式 。比如:一個訂單要支付 100塊錢,客戶端提交過來一個支付列表,比如:現金:50,掃支付寶碼:20,系統紅包賬戶支付:30元!
正常思維代碼實現
正常我們來實現這種需求,就直接
public void pay(List<payListDTO> payList) {
for (payList as pay) {
if (pay == “微信“) {
}
if (pay == “支付寶“) {
}
if (pay == “掃碼支付“) {
}
}
}
上面的代碼很簡單,也很明了!但是作為一個年長的開發者,是不能容忍的!至於為什么不能容忍,我這里也不表明客套話了,網上多的很!
業界內一神話:“高內聚,低耦合”。以這個視角去看上面的代碼,一個好的內聚模塊(這里可以看每一個 if
里做的事情) 應該是單獨的一個方法或者一個類,以方便代碼的復用性,解除方法隨着需求的迭代而變的很難維護。
那么我們嘗試着利用前人累積下的智慧來改造這段代碼!
改造
- 首先定義一個標准,定義抽象方法
public abstract class Payhander {
//定義支付行為
public abstract boolean pay(PayContext cnt)
}
- 定義現金支付類 實現 標准
@Component("cashPayHander")
class CashPayHander extends Payhander {
public boolean pay(PayContext cnt) {
//現金支付邏輯
}
}
- 定義余額支付類 實現 標准
@Component("balancePayHander")
class BalancePayHander extends Payhander {
public boolean pay(PayContext cnt) {
//余額支付邏輯
}
}
定義接口,和實現類簡單! 那么接下來是如何把這些類給利用起來?
通過理解責任鏈里描述 我們還要在每個實現類里定義一個指向下一個實現類的引用!
- 改造下抽象接口
public abstract class Payhander {
//定義一個指向下一個處理器的引用
protected Payhander nextHander;
// 這里我新加入一個待字類去實現的下一個引用注入器
public abstract void setNextHander(PayHander next)
//定義 getter,setter由子類實現
protected PayHander getNexthander() {
return nextHeader;
}
//定義支付行為
public abstract boolean pay(PayContext cnt)
}
- 改造下現金支付實現類
@Component("cashPayHander")
class CashPayHander extends Payhander {
// 這里我是利用Spring 的注入方式來實現自動注入 此時我們這現金支付注入下一個引用 為余額支付
@Resource
@Override
public void setNextHander(PayHander balancePayHander) {
this.nextHander = balancePayHander;
}
public boolean pay(PayContext cnt) {
//現金支付邏輯
if (super.getNexthander() != null) {
//調用下一個處理器
super.getNexthander().pay(cnt);
}
}
}
其他類的改造的類這里就不一一示例出!
經過這樣一改造,那么責任鏈的雛形就在我們腦海里出現了這樣的一副圖,每個支付業務邏輯單獨在每個實現類里做業務邏輯,單個類的利用性得到提高。再加入其他支付方式的時候,只要寫入實現,加入鏈表中即可。
一切看起來VeryGood
,但也有不好的地方!
缺點
- 如果維護人在每個實現類之前引用沒有處理好,容易開成環鏈,死循環。
- 每實現類都會被訪問一次,這個是鏈表的特性。