责任链被称为行为模式。这种模式的主要目标是避免将请求的发送者与接收者耦合,从而为多个对象提供处理请求的机会。 GoF定义的核心逻辑是:
"Gives more than one object an opportunity to handle a request by linking receiving objects together."
责任链允许多个类独立于链上的任何其他对象来尝试处理请求。一旦请求被处理,它就完成了它在链中的旅程。
可以在链中添加或删除额外的处理程序,而无需修改任何具体处理程序内部的逻辑。
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 操作系统中的事件处理机制,其中可以从鼠标、键盘或一些自动生成的事件中生成事件。所有此类事件都可以由多个处理程序处理,并在运行时找到正确的处理程序。
更一般的例子可以是对呼叫中心的服务请求。此请求可以在前台级别、主管级别或任何更高级别处理。请求的正确处理程序仅在运行时在请求遍历各个级别时才知道。我们将在这篇文章中解决这种情况。
1) Handler :这可以是一个接口,主要接收请求并将请求分派给处理程序链。它仅引用链中的第一个处理程序,对其余处理程序一无所知。
2) 具体处理程序:这些是按顺序链接的请求的实际处理程序。
3) Client :请求的发起者,这将访问处理程序来处理它。
问题陈述是为支持服务系统设计一个由前台、主管、经理和主管组成的系统。任何客户都可以致电前台并要求解决方案。如果前台能够解决问题,它会;否则将传递给主管。同样,主管会尝试解决问题,如果他能解决,他就会解决;否则传递给经理。同样,经理将解决问题或传递给主管。导演要么解决问题,要么拒绝它。
上述问题很适合使用责任链模式。我们可以定义每个级别的处理程序,即支持台、主管、经理和主管。然后我们可以定义一个链来处理支持请求。此链必须遵循以下顺序:
Support desk > supervisor > manager > director
上面的链也可以使用 java 中的编程解决方案来管理,但在本教程中,我使用 spring 来注入依赖项,从而形成这个链。此外,系统将首先将请求分配给前台。
我已经绘制了解决方案中涉及的所有实体的结构,如下所示。
以下是使用责任链设计模式参与支持服务实施的所有参与者的源代码:
ServiceLevel.java
package com.cundage; public enum ServiceLevel { LEVEL_ONE, LEVEL_TWO, LEVEL_THREE, LEVEL_FOUR, INVALID_REQUEST }
ServiceRequest.java
package com.cundage.data; import com.cundage.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
package com.cundage.handler; import com.cundage.data.ServiceRequest; public interface SupportServiceItf { public void handleRequest(ServiceRequest request); }
SupportService.java
package com.cundage.handler; import com.cundage.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
package com.cundage.handler; import com.cundage.ServiceLevel; import com.cundage.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
package com.cundage.handler; import com.cundage.ServiceLevel; import com.cundage.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
package com.cundage.handler; import com.cundage.ServiceLevel; import com.cundage.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
package com.cundage.handler; import com.cundage.ServiceLevel; import com.cundage.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
<?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.cundage.handler.SupportService"> <property name="handler" ref="frontDeskSupport"></property> </bean> <bean id="frontDeskSupport" class="com.cundage.handler.FrontDeskSupport"> <property name="next" ref="supervisorSupport"></property> </bean> <bean id="supervisorSupport" class="com.cundage.handler.SupervisorSupport"> <property name="next" ref="managerSupport"></property> </bean> <bean id="managerSupport" class="com.cundage.handler.ManagerSupport"> <property name="next" ref="directorSupport"></property> </bean> <bean id="directorSupport" class="com.cundage.handler.DirectorSupport"></bean> </beans>
我将在链中传递各种级别的支持请求,它们将由正确的级别处理。任何无效的请求都将按计划被拒绝。
package com.cundage; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.cundage.data.ServiceRequest; import com.cundage.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
要下载上述示例应用程序的源代码,请单击以下链接。
每次由于客户端请求链末端的资源而通过链传递请求/响应对时,过滤器的 doFilter
方法都会被容器调用。传入此方法的 FilterChain 允许 Filter 将请求和响应传递给链中的下一个实体。
如果当前为给定的消息级别启用了记录器,则给定的消息将转发到所有已注册的输出处理程序对象。
我希望这篇文章对您对责任链模式的理解增加了一些知识。如果您有任何疑问,请发表评论。
快乐学习!!
地址:https://www.cundage.com/article/chain-of-responsibility-design-pattern.html