责任链模式你用对了吗

  • Post author:
  • Post category:其他


责任链是很多框架和项目常用的设计模式,可有效保证代码的可扩展性、复用性、高内聚低耦合,责任链模式本身并不复杂,但是很多博客的示例代码的用法属于“教科书”式的实践,不适合在实际软件工程中的运用,笔者将结合在项目中使用的心得体会,谈谈使用责任链模式的正确姿势。



一、何谓责任链

责任链的设计模式其实就是把若干个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);
        }
    }
    
}

更多内容欢迎关注个人微信公众号,一起成长!

在这里插入图片描述



版权声明:本文为song19890528原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。