企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 责任链设计模式 > 原文: [https://howtodoinjava.com/design-patterns/behavioral/chain-of-responsibility-design-pattern/](https://howtodoinjava.com/design-patterns/behavioral/chain-of-responsibility-design-pattern/) [责任链](https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern "Chain-of-responsibility_pattern")被称为行为型模式。 这种模式的主要目的是避免将请求的发送方耦合到接收方,从而为多个对象提供了处理请求的机会。 GoF 定义的核心逻辑是: ```java "Gives more than one object an opportunity to handle a request by linking receiving objects together." ``` 责任链允许许多类尝试处理请求,而与链上的任何其他对象无关。 处理完请求后,它就完成了整个流程。 可以在链中添加或删除额外的处理器,而无需修改任何具体处理器内部的逻辑。 ```java Sections in this post: Suggested usage Participants in the solution Sample problem to be solved Proposed solution Class diagram of participants Sourcecode of participants Test the application Download sourecode link Reference implementations in JDK ``` ## 建议用法 当多个对象可以处理一个请求并且处理器不必是特定的对象时,建议使用此模式。 另外,处理器是在运行时确定的。 请注意,任何处理器都不处理的请求是有效的用例。 例如,Windows OS 中的事件处理机制,可以从鼠标,键盘或某些自动生成的事件生成事件。 所有这些事件都可以由多个处理器处理,并且在运行时可以找到正确的处理器。 更一般的例子可以是对呼叫中心的服务请求。 可以在前台,主管或任何更高级别处理此请求。 仅当在各个级别上遍历请求时,才在运行时知道正确的请求处理器。 我们将在这篇文章中解决这种情况。 ## 解决方案中的参与者 **1)`Handler`**:这可以是一个主要接收请求并将请求分派到处理器链的接口。 它仅引用链中的第一个处理器,而对其余处理器一无所知。 **2)`ConcreteHandler`**:这些是按某些顺序链接的请求的实际处理器。 **3)`Client`**:请求的始发者,它将访问处理器来处理它。 ![Participants in chain of responsibility](https://img.kancloud.cn/48/ac/48ac5ffeb620e9a903eeb43295f7dee8_433x165.png) 责任链中的参与者 ## 要解决的示例问题 问题陈述是为**支持服务系统**设计一个系统,该系统由前台,主管,经理和主管组成。 任何客户都可以致电前台,并寻求解决方案。 如果前台能够解决问题,它将解决; 否则将转交给主管。 同样,主管将尝试解决该问题,如果他能够解决,则将解决; 否则传给经理。 同样,经理将解决问题或转给董事。 导演将解决该问题或拒绝它。 ## 建议的解决方案 以上问题是使用责任链模式的良好人选。 我们可以在每个级别上定义处理器,即支持台,主管,经理和主管。 然后,我们可以定义一条链来处理支持请求。 该链必须遵循以下顺序: ```java Support desk > supervisor > manager > director ``` 上面的链也可以使用 Java 中的编程解决方案进行管理,但是在本教程中,我将使用 spring 注入依赖项,从而形成该链。 同样,系统将首先将请求仅分配给前台。 ## 参与者的类图 我已经绘制了解决方案中涉及的所有实体的结构,如下所示。 ![Chain of responsibility class diagram](https://img.kancloud.cn/f9/54/f9544c4bb861ed692fbc54d81de3c71f_1219x550.png) 支持服务系统:类图 ## 参与者的源代码 以下是使用责任链设计模式实现支持服务的所有参与者的源代码: **`ServiceLevel.java`** ```java package com.howtodoinjava; public enum ServiceLevel { LEVEL_ONE, LEVEL_TWO, LEVEL_THREE, LEVEL_FOUR, INVALID_REQUEST } ``` **`ServiceRequest.java`** ```java package com.howtodoinjava.data; import com.howtodoinjava.ServiceLevel; public class ServiceRequest { private ServiceLevel type; private String conclusion = null; public ServiceLevel getType() { return type; } public void setType(ServiceLevel type) { this.type = type; } public String getConclusion() { return conclusion; } public void setConclusion(String conclusion) { this.conclusion = conclusion; } } ``` **`SupportServiceItf.java`** ```java package com.howtodoinjava.handler; import com.howtodoinjava.data.ServiceRequest; public interface SupportServiceItf { public void handleRequest(ServiceRequest request); } ``` **`SupportService.java`** ```java package com.howtodoinjava.handler; import com.howtodoinjava.data.ServiceRequest; public class SupportService implements SupportServiceItf { private SupportServiceItf handler = null; public SupportServiceItf getHandler() { return handler; } public void setHandler(SupportServiceItf handler) { this.handler = handler; } @Override public void handleRequest(ServiceRequest request) { handler.handleRequest(request); } } ``` **`FrontDeskSupport.java`** ```java package com.howtodoinjava.handler; import com.howtodoinjava.ServiceLevel; import com.howtodoinjava.data.ServiceRequest; public class FrontDeskSupport implements SupportServiceItf { private SupportServiceItf next = null; public SupportServiceItf getNext() { return next; } public void setNext(SupportServiceItf next) { this.next = next; } @Override public void handleRequest(ServiceRequest service) { if(service.getType() == ServiceLevel.LEVEL_ONE) { service.setConclusion("Front desk solved level one reuqest !!"); } else { if(next != null){ next.handleRequest(service); } else { throw new IllegalArgumentException("No handler found for :: " + service.getType()); } } } } ``` **`SupervisorSupport.java`** ```java package com.howtodoinjava.handler; import com.howtodoinjava.ServiceLevel; import com.howtodoinjava.data.ServiceRequest; public class SupervisorSupport implements SupportServiceItf { private SupportServiceItf next = null; public SupportServiceItf getNext() { return next; } public void setNext(SupportServiceItf next) { this.next = next; } @Override public void handleRequest(ServiceRequest request) { if(request.getType() == ServiceLevel.LEVEL_TWO) { request.setConclusion("Supervisor solved level two reuqest !!"); } else { if(next != null){ next.handleRequest(request); } else { throw new IllegalArgumentException("No handler found for :: " + request.getType()); } } } } ``` **`ManagerSupport.java`** ```java package com.howtodoinjava.handler; import com.howtodoinjava.ServiceLevel; import com.howtodoinjava.data.ServiceRequest; public class ManagerSupport implements SupportServiceItf { private SupportServiceItf next = null; public SupportServiceItf getNext() { return next; } public void setNext(SupportServiceItf next) { this.next = next; } @Override public void handleRequest(ServiceRequest request) { if(request.getType() == ServiceLevel.LEVEL_THREE) { request.setConclusion("Manager solved level three reuqest !!"); } else { if(next != null){ next.handleRequest(request); } else { throw new IllegalArgumentException("No handler found for :: " + request.getType()); } } } } ``` **`DirectorSupport.java`** ```java package com.howtodoinjava.handler; import com.howtodoinjava.ServiceLevel; import com.howtodoinjava.data.ServiceRequest; public class DirectorSupport implements SupportServiceItf { private SupportServiceItf next = null; public SupportServiceItf getNext() { return next; } public void setNext(SupportServiceItf next) { this.next = next; } @Override public void handleRequest(ServiceRequest request) { if(request.getType() == ServiceLevel.LEVEL_FOUR) { request.setConclusion("Director solved level four reuqest !!"); } else { if(next != null){ next.handleRequest(request); } else { request.setConclusion("You problem is none of our business"); throw new IllegalArgumentException("You problem is none of our business :: " + request.getType()); } } } } ``` **`applicationConfig.xml`** ```java <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <bean id="supportService" class="com.howtodoinjava.handler.SupportService"> <property name="handler" ref="frontDeskSupport"></property> </bean> <bean id="frontDeskSupport" class="com.howtodoinjava.handler.FrontDeskSupport"> <property name="next" ref="supervisorSupport"></property> </bean> <bean id="supervisorSupport" class="com.howtodoinjava.handler.SupervisorSupport"> <property name="next" ref="managerSupport"></property> </bean> <bean id="managerSupport" class="com.howtodoinjava.handler.ManagerSupport"> <property name="next" ref="directorSupport"></property> </bean> <bean id="directorSupport" class="com.howtodoinjava.handler.DirectorSupport"></bean> </beans> ``` ## 测试应用 我将在链下传递各种级别的支持请求,这些请求将由正确的级别处理。 任何无效的请求将按计划被拒绝。 ```java package com.howtodoinjava; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.howtodoinjava.data.ServiceRequest; import com.howtodoinjava.handler.SupportService; public class TestChainOfResponsibility { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("application-config.xml"); SupportService supportService = (SupportService) context.getBean("supportService"); ServiceRequest request = new ServiceRequest(); request.setType(ServiceLevel.LEVEL_ONE); supportService.handleRequest(request); System.out.println(request.getConclusion()); request = new ServiceRequest(); request.setType(ServiceLevel.LEVEL_THREE); supportService.handleRequest(request); System.out.println(request.getConclusion()); request = new ServiceRequest(); request.setType(ServiceLevel.INVALID_REQUEST); supportService.handleRequest(request); System.out.println(request.getConclusion()); } } <strong>Output:</strong> Front desk solved level one reuqest !! Manager solved level three reuqest !! Exception in thread "main" java.lang.IllegalArgumentException: You problem is none of our business :: INVALID_REQUEST ``` 要下载上述示例应用的源代码,请单击以下链接。 ## JDK 中的参考实现 * [`javax.servlet.Filter#doFilter()`](https://docs.oracle.com/javaee/6/api/javax/servlet/Filter.html#doFilter%28javax.servlet.ServletRequest,%20javax.servlet.ServletResponse,%20javax.servlet.FilterChain%29 "dofilter chain") 每当客户端对链末端的资源提出请求时,每次通过链传递请求/响应对时,容器都会调用`Filter`的`doFilter`方法。 传入此方法的`FilterChain`允许`Filter`将请求和响应传递给链中的下一个实体。 * [`java.util.logging.Logger#log`](https://docs.oracle.com/javase/6/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29 "logger.log") 如果当前为给定消息级别启用了记录器,则将给定消息转发到所有已注册的输出`Handler`对象。 我希望这篇文章能为您对责任链模式的理解增加一些知识。 如有任何疑问,请发表评论。 **祝您学习愉快!**