責任鏈是很多框架和項目常用的設計模式,可有效保證代碼的可擴展性、複用性、高內聚低耦合,責任鏈模式本身並不複雜,但是很多博客的示例代碼的用法屬於“教科書”式的實踐,不適合在實際軟件工程中的運用,筆者將結合在項目中使用的心得體會,談談使用責任鏈模式的正確姿勢。
一、何謂責任鏈
責任鏈的設計模式其實就是把若干個request處理器,以“鏈”的形式組織起來,“鏈”是該設計模式的關鍵和核心問題。
責任鏈模式可以動態地組織和分配處理器,比較靈活,代碼的可擴展性也很好,需要加新的處理器時,直接上鍊就好。
另外每個處理器都是一個單獨的類,這樣處理器之間高內聚、低耦合,代碼的複用性也比較高。
二、責任鏈使用的誤區
使用責任鏈的一個誤區是通過遞歸的方式來執行處理器,遞歸最大的不足就是性能很差,如果責任鏈過長還可能會發生棧溢出。這就是屬於“教科書”式的用法,很多博客的代碼上都是這麼寫的,這是不能用在實際的軟件開發中的,性能是其最大的bug。
三、責任鏈應用的正確姿勢
** 1.要使用好責任鏈模式,要解決一下幾個問題:**
- 以什麼樣的鏈來組織處理器
Java中常用的“鏈”的數據結構是List,比如ArrryList與LinkedList,我們可以使用List數據結構來組織不同的處理器成爲一條鏈。
- 如何保證處理器之間執行的順序性
不使用遞歸,使用for循環來保證責任鏈執行的順序性,代碼反而更簡潔和優雅,且不存在性能問題。
- 何時加載責任鏈
一般來說,某個請求的處理器之間的執行順序是確定,我們可以在bean初始化的時候來完成責任鏈的組裝。InitializingBean#afterPropertiesSet可以用來在處理器都初始化完成後,進行責任鏈的組裝。
2.實例代碼
代碼主要包括,一個接口,若干實現類、組裝和執行類
下面通過一個參數校驗責任鏈的demo來展示責任鏈的用法。
/**
* 參數校驗接口,這是責任鏈
*/
public interface ParamCheckService {
boolean paramCheck(RequestParam param);
}
/**
* 參數校驗接口實現類
*/
@Service("amountCheckService")
public class AmountCheckServiceImpl implements ParamCheckService {
private Logger logger = LoggerFactory.getLogger(AmountCheckServiceImpl.class);
@Override
public boolean paramCheck(RequestParam param) {
logger.info("執行數量校驗處理器");
return param.getAmount() > 0;
}
}
/**
* 參數校驗接口實現類
*/
@Service("moneyCheckService")
public class MoneyCheckServiceImpl implements ParamCheckService {
private org.slf4j.Logger logger = LoggerFactory.getLogger(MoneyCheckServiceImpl.class);
@Override
public boolean paramCheck(RequestParam param) {
logger.info("執行金額校驗處理器");
BigDecimal money = param.getMoney();
if (money.compareTo(new BigDecimal(0)) < 0) {
return false;
}
return true;
}
}
/**
* 責任鏈的組裝與執行類
*/
@Service
public class ParamCheckChain implements InitializingBean {
@Autowired
private ParamCheckService moneyCheckService;
@Autowired
private ParamCheckService amountCheckService;
/**
* 通過ArrayList,把處理器組織成鏈
*/
private List<ParamCheckService> checkChain = new ArrayList<>();
/**
* 對象初始化時進行責任鏈的組裝,afterPropertiesSet會在處理器注入完成後執行
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
//此處的添加順序即是責任鏈的執行順序
checkChain.add(moneyCheckService);
checkChain.add(amountCheckService);
}
/**
* 責任鏈執行方法,通過for循環來順序執行處理器
* @param param
* @return
*/
public void chainExcute(RequestParam param) {
for (ParamCheckService checkService : checkChain) {
checkService.paramCheck(param);
}
}
}
更多內容歡迎關注個人微信公衆號,一起成長!