设计模式-职责链模式(Chain of Responsibility)
设计模式-职责链模式(Chain of Responsibility)
概要
记忆关键词:传递请求,职责链接
定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将多个对象连成一条链,并沿着这条链发送请求,直到有一个对象处理它为止。
分析:当客户提交一个请求,请求是沿链传递直至有一个对象负责处理它。
类型:行为型
职责链模式结构图如下:
一、能解决什么问题?
责任链模式通过将请求的发送者和接收者解耦,使得发送者不需要知道哪个接收者会处理请求,接收者也不知道请求的发送者是谁。这种解耦提高了系统的灵活性和可扩展性。
二、涉及的角色
1. Handler(抽象处理者)
代码示例:
1 abstract public class Handler { 2 protected Handler successor; 3 4 public void setSuccessor(Handler successor) { 5 this.successor = successor; 6 } 7 8 abstract String handleRequest(String msg); 9 10 }
2. ConcreteHandler(具体处理者)
职责链模式的每一个具体 Handler类都继承自统一的抽象类
代码示例如下:
具体处理者1
1 public class HandlerA extends Handler{ 2 @Override 3 String handleRequest(String msg) { 4 if(msg.contains("a")){ 5 msg = msg.replace('a', '*'); 6 } else if(this.successor != null){ 7 msg = this.successor.handleRequest(msg); 8 } 9 return msg; 10 } 11 }
具体处理者2:
1 public class HandlerB extends Handler{ 2 @Override 3 String handleRequest(String msg) { 4 if(msg.contains("b")){ 5 msg = msg.replace('b', '*'); 6 } else if(this.successor != null){ 7 msg = this.successor.handleRequest(msg); 8 } 9 return msg; 10 } 11 }
具体处理者3:
1 public class HandlerC extends Handler{ 2 @Override 3 String handleRequest(String msg) { 4 if(msg.contains("c")){ 5 msg = msg.replace('c', '*'); 6 } else if(this.successor != null){ 7 msg = this.successor.handleRequest(msg); 8 } 9 return msg; 10 } 11 }
3. Client(客户类)
定义链的结构
代码示例:
1 public class Client { 2 public static void main(String[] args) { 3 Handler handlerA = new HandlerA(); 4 Handler handlerB = new HandlerB(); 5 Handler handlerC = new HandlerC(); 6 7 handlerA.setSuccessor(handlerB); 8 handlerB.setSuccessor(handlerC); 9 System.out.println(handlerA.handleRequest("apple")); 10 System.out.println(handlerA.handleRequest("bicycle")); 11 System.out.println(handlerA.handleRequest("color")); 12 } 13 } 14 15 //运行结果 16 *pple 17 *icycle 18 *olor
三、优缺点分析
1. 优点
1) 由于是在客户端定义链的结构,因此可以随时地增加或者修改处理一个请求的结构,增强了给对象指派职责的灵活性
2)责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
3)责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
2. 缺点
1)不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
2)对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
3)职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
4)对代码Debug不太友好。在代码逻辑比较复杂,链路比较长的情况下,Debug可能要深入很多层。
四、应用场景
1. 过滤器Filter
当客户端对Web应用发出HTTP请求的时候,会首先经过Tomcat容器的一层层过滤器(Filter),过滤器会针对请求的访问权限、参数合法性等方面进行验证和过滤。
2. 拦截器
在Spring框架中,责任链模式被广泛应用于各种处理链中,如Spring Security的过滤器链、Spring MVC的拦截器链等。
下面是一个Spring MVC拦截器链的简单示例:
1 public class LoggingInterceptor implements HandlerInterceptor { 2 @Override 3 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { 4 System.out.println("LoggingInterceptor: Pre-handle"); 5 return true; 6 } 7 8 @Override 9 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { 10 System.out.println("LoggingInterceptor: Post-handle"); 11 } 12 13 @Override 14 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { 15 System.out.println("LoggingInterceptor: After completion"); 16 } 17 } 18 19 @Configuration 20 public class WebConfig implements WebMvcConfigurer { 21 @Override 22 public void addInterceptors(InterceptorRegistry registry) { 23 registry.addInterceptor(new LoggingInterceptor()); 24 // 可以继续添加其他拦截器 25 } 26 }
在这个示例中,LoggingInterceptor作为一个拦截器,可以在请求处理的不同阶段进行操作。多个拦截器可以按顺序执行,形成一个责任链。
3. 请假条审批
用责任链模式设计一个请假条审批模块。
分析:假如规定学生请假小于或等于 2 天,班主任可以批准;小于或等于 7 天,系主任可以批准;小于或等于 10 天,院长可以批准;其他情况不予批准;这个实例适合使用职责链模式实现。
五、模式的扩展
职责链模式存在以下两种情况:
1. 纯的职责链模式
一个请求必须被某一个处理者对象所接收,且一个具体处理者对某个请求的处理只能采用以下两种行为之一:自己处理(承担责任);把责任推给下家处理。
2. 不纯的职责链模式
允许出现某一个具体处理者对象在承担了请求的一部分责任后又将剩余的责任传递给下家的情况,且一个请求可以最终不被任何接收端对象所接收。
六、总结
责任链模式通过解耦请求的发送者和接收者,动态组合处理者,简化对象的职责,以及增强系统的灵活性,解决了处理请求时的诸多问题。在实际应用中,责任链模式广泛用于日志处理、事件处理、请求处理等场景。
参考链接:https://juejin.cn/post/7080898925674430478