责任链是很多框架和项目常用的设计模式,可有效保证代码的可扩展性、复用性、高内聚低耦合,责任链模式本身并不复杂,但是很多博客的示例代码的用法属于“教科书”式的实践,不适合在实际软件工程中的运用,笔者将结合在项目中使用的心得体会,谈谈使用责任链模式的正确姿势。
一、何谓责任链
责任链的设计模式其实就是把若干个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);
}
}
}
更多内容欢迎关注个人微信公众号,一起成长!