责任链模式¶
责任链模式适合业务需要按步骤执行,业务具有很明显的流程性、顺序性,任务发送者和接受者需要松耦合的情况, 专门对流程控制和处理来使用。 它主要是还是松耦合,和大多数设计模式一样,扩展性好又灵活,当然如果流程很长,责任链中请求的处理时间过长,可能会影响性能, 中间那里有问题了,你找起来还麻烦。
这个模式在各大开源框架都有广泛使用,比如spring-cloud-gateway有一个FilteringWebHandler, Spring Security有一个FilterChainProxy。 简单一点,举个例子:SaaS系统里有一个请假流程,公司的要求可能是要达成怎样的步骤, 最终你才可以成功。
又或者有一个接口,你要校验很多东西,你要检验参数、黑名单,你又要检验规则拦截、做安全校验,正常是如下:
那这样是普通的写法,它能用,但是违背开闭原则,即当我们扩展功能的时候需要去修改主流程,无法做到对修改关闭、对扩展开放。 而且如果要修改顺序,还要改业务接口里面的代码。
🏀代码样例¶
那如何改一下呢?首先要有一个抽象类,把校验或拦截的动作抽出来。
@Getter
@Setter
public abstract class AbstractHandler {
// 责任链中的下一个对象
private AbstractHandler nextHandler;
/**
* 具体参数拦截逻辑,给子类去实现,参数就是你要校验或拦截的东西,就是责任链要操作的对象
*/
public void filter(int a, int b) {
doFilter(a, b);
if (getNextHandler() != null) {
getNextHandler().filter(a, b);
}
}
abstract void doFilter(int a, int b);
}
那么每一个要校验的对象,就是一个实现类,对应如下:
最后就是将它们放到list里面,便利一下执行就可以了。
@Component("ChainPatternDemo")
public class ChainPatternDemo {
// 自动注入各个责任链的对象
@Autowired
private List<AbstractHandler> abstractHandleList;
@Getter
@Setter
private AbstractHandler abstractHandler;
// spring注入后自动执行,责任链的对象连接起来
@PostConstruct
public void initializeChainFilter() {
for (int i = 0; i < abstractHandleList.size(); i++) {
if (i == 0) {
abstractHandler = abstractHandleList.get(0);
} else {
AbstractHandler currentHander = abstractHandleList.get(i - 1);
AbstractHandler nextHander = abstractHandleList.get(i);
currentHander.setNextHandler(nextHander);
}
}
}
// 直接调用这个方法使用
public String exec(int a, int b) {
abstractHandler.filter(a, b);
return "返回你想返回的东西,在责任链走完后";
}
}
🐔使用方式¶
那里要校验,就直接注入这个demo,走一下exec()
方法就行了。这个参数看需求添加。