23种设计模式之责任链模式
责任链设计模式是一种行为型设计模式,它允许多个对象依次处理一个请求,直到有一个对象处理这个请求为止。
主要角色和结构
- 抽象处理者(Handler):
- 定义了处理请求的接口,其中包含一个指向下一个处理者的引用。
- 通常有一个抽象方法来处理请求,子类需要实现这个方法。
- 具体处理者(ConcreteHandler):
- 实现了抽象处理者的接口,具体处理请求。
- 如果自己无法处理请求,则将请求转发给下一个处理者。
工作原理
当一个请求产生时,它会被传递给责任链中的第一个处理者。这个处理者会尝试处理请求,如果它能够处理,就处理并结束请求的传递;如果不能处理,它会将请求传递给下一个处理者,如此继续,直到请求被处理或者到达责任链的末尾。
简单实现 - 学生成绩打印
学生的成绩打印,成绩大于80分-优秀,成绩60~80分合格,成绩小于60分不合格。
abstract class ScoreHandler {
protected ScoreHandler nextHandler;
public void setNextHandler(ScoreHandler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handleScore(int score);
}
class ExcellentScoreHandler extends ScoreHandler {
@Override
public void handleScore(int score) {
if (score > 80) {
System.out.println("成绩优秀");
} else if (nextHandler!= null) {
nextHandler.handleScore(score);
}
}
}
class PassScoreHandler extends ScoreHandler {
@Override
public void handleScore(int score) {
if (score >= 60 && score <= 80) {
System.out.println("成绩及格");
} else if (nextHandler!= null) {
nextHandler.handleScore(score);
}
}
}
class FailScoreHandler extends ScoreHandler {
@Override
public void handleScore(int score) {
if (score < 60) {
System.out.println("成绩不及格,需重修");
} else if (nextHandler!= null) {
nextHandler.handleScore(score);
}
}
}
使用:在使用时需要创建责任链。也就是需要设置下一个处理器setNextHandler
。
public class Main {
public static void main(String[] args) {
ScoreHandler excellentHandler = new ExcellentScoreHandler();
ScoreHandler passHandler = new PassScoreHandler();
ScoreHandler failHandler = new FailScoreHandler();
excellentHandler.setNextHandler(passHandler);
passHandler.setNextHandler(failHandler);
excellentHandler.handleScore(75);
excellentHandler.handleScore(90);
excellentHandler.handleScore(45);
}
}
在这个例子中,根据学生的成绩,不同的处理者会打印出相应的成绩状态。如果一个处理者不能处理当前成绩,它会将请求传递给下一个处理者。
执行结果
成绩及格
成绩优秀
成绩不及格,需重修
优点
- 降低了对象之间的耦合度:请求的发送者和接收者之间没有直接的耦合关系,发送者只需要将请求发送到责任链上,而不需要知道具体由哪个对象来处理请求。
- 增强了系统的灵活性:可以动态地添加或删除处理者,以及改变处理者的顺序,而不影响系统的其他部分。
- 提高了代码的可维护性:每个处理者只负责自己的处理逻辑,代码的职责更加清晰,易于维护和扩展。
责任链 - 缺点
- 存在请求可能不被处理的风险,因为无法确保责任链中的某个处理者一定会处理该请求。
- 当责任链过长时,会带来较大的性能开销,因为请求需要依次经过多个处理者,可能导致处理时间延长。
- 调试过程较为复杂,由于请求在多个处理者之间传递,出现问题时难以快速确定具体的问题节点。
责任链 - 应用场景
- 异常处理:可通过责任链模式,将不同类型的异常依次交由特定的处理者进行处理,确保异常得到妥善解决。
- 中间件:在中间件的实现中,责任链模式能让不同的中间件组件依次对请求进行处理,增强系统的灵活性和可扩展性。
- GUI:在图形用户界面系统中,事件可以通过责任链进行传递和处理,不同的组件可根据自身能力处理特定事件。
- 工作流:适用于工作流场景,不同的任务节点可以组成责任链,依次处理任务,直至完成整个工作流程。
责任链模式在Spring中的使用
1、DispatcherServlet
在DispatcherServlet
处理请求的过程中就用到了责任链模式。
在 Spring MVC 中,当一个请求到达DispatcherServlet
后,会经过一系列的拦截器(HandlerInterceptor)进行处理。这些拦截器组成了一个责任链,每个拦截器可以在请求处理的不同阶段进行预处理(preHandle)、后处理(postHandle)以及请求完成后的处理(afterCompletion)。如果某个拦截器的preHandle
方法返回false
,则后续的拦截器和处理器将不会被执行。
这种方式使得请求的处理更加灵活,可以方便地添加、删除或调整拦截器的顺序,而不影响核心的请求处理逻辑。