一、责任链模式定义
责任链模式是一种设计模式,它定义了一个责任链,链上的每个对象都有机会处理请求,直到某个对象处理该请求为止。这种设计模式可以避免请求发送者与接收者耦合在一起,使得多个对象都有可能接收请求,并且可以动态地重新组织和分配责任
二、责任链举例
当我们想要请假的时候,如果请假天数在一天,我们可以让班长处理,如果请假天数大于一天小于三天,班长无权处理,这时候就要上报辅导员了,如果大于三天的话,就要让校长来处理了。这个请假的请求就形成了班长-》辅导员-》校长这样一条链路,直到有人处理这个请求。
三、代码
抽象处理类
//抽象处理类
public abstract class AbstractChainHandler {
private AbstractChainHandler nextHandler;
public AbstractChainHandler() {
}
public void setNextHandler(AbstractChainHandler nextHandler) {
this.nextHandler = nextHandler;
}
protected String doNextHandler(int days) {
return nextHandler.handler(days);
}
public abstract String handler(int days);
}
班长处理类
//班长处理类
public class MonitorHandler extends AbstractChainHandler{
private AbstractChainHandler nextHandler;
public MonitorHandler() {
}
@Override
public String handler(int days) {
System.out.println("我是班长");
if(days <= 1) {
return "请假一天之内我批准了!";
}
System.out.println("无权处理,交给别人");
return doNextHandler(days);
}
}
辅导员处理类
//辅导员处理类
public class TeacherHandler extends AbstractChainHandler{
private AbstractChainHandler nextHandler;
public TeacherHandler() {
}
@Override
public String handler(int days) {
System.out.println("我是辅导员");
if(days <= 3) {
return "请假三天内我批准了!";
}
System.out.println("无权处理,交给别人");
return doNextHandler(days);
}
}
校长处理类
//校长处理类
public class PresidentHandler extends AbstractChainHandler{
private AbstractChainHandler nextHandler;
public PresidentHandler() {
}
@Override
public String handler(int days) {
return "我是校长,批准了!";
}
}
测试类
public class Test {
public static void main(String[] args) {
MonitorHandler monitorHandler = new MonitorHandler();
TeacherHandler teacherHandler = new TeacherHandler();
PresidentHandler presidentHandler = new PresidentHandler();
monitorHandler.setNextHandler(teacherHandler);
teacherHandler.setNextHandler(presidentHandler);
System.out.println(monitorHandler.handler(10));
}
}
测试结果
我是班长
无权处理,交给别人
我是辅导员
无权处理,交给别人
我是校长,批准了!
在测试代码中,我们自己组装了一条责任链,请求被校长处理了,但是如果责任链很长的话,我们要一直组装,所以我们可以优化一下代码,将处理类注入spring并使用@Order注解控制责任链的执行顺序。
在处理类中加上@Component注解,其中班长处理类加上@Order(1),辅导员处理类加上@Order(2),校长处理类加上@Order(3)
组装责任链
@Component
public class ChainHandlerConfig {
/**
* 利用Spring注入特性,按照 @Order 从小到达排序注入到集合中
*/
@Resource
private List<AbstractChainHandler> chainHandlers;
private AbstractChainHandler firstHandler;
/**
* 组装处理链
*/
@PostConstruct
private void constructChain() {
if (CollUtil.isEmpty(chainHandlers)) {
throw new SLException("not found chain handler!");
}
//处理链中第一个节点
firstHandler = chainHandlers.get(0);
for (int i = 0; i < chainHandlers.size(); i++) {
if (i == chainHandlers.size() - 1) {
//最后一个处理链节点
chainHandlers.get(i).setNextHandler(null);
} else {
//设置下游节点
chainHandlers.get(i).setNextHandler(chainHandlers.get(i + 1));
}
}
}
public String findHandler(int days) {
//从第一个节点开始处理
return firstHandler.handler(days);
}
}
当责任链要添加新的处理节点的时候,只要用@Order注解控制执行顺序就可以了,无需更改其他代码,这样就具有良好的可扩展性,符合开闭原则。
三、责任链优缺点
优点:
1.降低对象之间的耦合度:责任链模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
2.增强系统的可扩展性:可以根据需要增加新的请求处理类,满足开闭原则。
3.增强给对象指派职责的灵活性:当工作流程发生变化时,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
4.简化对象之间的连接:每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
5.责任分担:每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
缺点:
1.不能保证每个请求一定被处理:由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
2.对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
准备出一期讲解aop中策略模式跟责任链模式的使用