责任链设计模式

责任链已知为一种行为模式。这种模式的主要目的是避免将请求的发送方耦合到接收方,从而为多个对象提供了处理请求的机会。GoF定义的核心逻辑是:

“通过将接收对象链接在一起,使多个对象有机会处理请求。”

责任链允许许多类尝试处理请求,而与链上的任何其他对象无关。处理完请求后,它就完成了整个链的过程。

可以在链中添加或删除额外的处理程序,而无需修改任何具体处理程序内部的逻辑。

这篇文章中的部分:

建议用法
解决方案的参与者
需要解决的样本问题
拟议的解决方案
参加者的班级图
参与者的源代码
测试应用
下载sourecode链接
JDK中的参考实现

建议用法

当多个对象可以处理请求并且处理程序不必是特定对象时,建议使用此模式。另外,处理程序是在运行时确定的。请注意,任何处理程序都不处理的请求是有效的用例。

例如,Windows OS中的事件处理机制,可以从鼠标,键盘或某些自动生成的事件生成事件。所有这些事件都可以由多个处理程序处理,并且在运行时可以找到正确的处理程序。

更一般的例子可以是对呼叫中心的服务请求。可以在前台,主管或任何更高级别处理此请求。仅当在各个级别上遍历请求时,才在运行时知道正确的请求处理程序。我们将在这篇文章中解决这种情况。

解决方案的参与者

1)处理程序:这可以是一个主要接收请求并将请求分派给处理程序链的接口。它仅引用链中的第一个处理程序,而对其余处理程序一无所知。

2)具体处理程序:这些是按某些顺序链接的请求的实际处理程序。

3)客户:请求的发起者,它将访问处理程序以处理它。

责任链中的参与者
责任链中的参与者

需要解决的样本问题

问题陈述是设计一个由前台,主管,经理和主管组成的支持服务系统。任何客户都可以致电前台,并寻求解决方案。如果前台能够解决问题,它将解决;否则将转交给主管。同样,主管将尝试解决该问题,如果他能够解决,则将解决;否则交给经理。同样,经理将解决问题或转给董事。导演将解决该问题或拒绝它。

拟议的解决方案

以上问题是使用责任链模式的良好人选。我们可以在每个级别定义处理程序,即支持台,主管,经理和主管。然后,我们可以定义一条链来处理支持请求。该链必须遵循以下顺序:

服务台>主管>经理>总监

上面的链也可以使用Java中的编程解决方案进行管理,但是在本教程中,我将使用spring注入依赖项,从而形成该链。同样,系统将首先将请求仅分配给前台。

参加者的班级图

我已经绘制了解决方案中涉及的所有实体的结构,如下所示。

责任链类图
支持服务系统:类图

参与者的源代码

以下是使用责任链设计模式实施支持服务的所有参与者的源代码:

ServiceLevel.java

package com.how2codex;
public enum ServiceLevel
{
    LEVEL_ONE, LEVEL_TWO, LEVEL_THREE, LEVEL_FOUR, INVALID_REQUEST
}

ServiceRequest.java

package com.how2codex.data;
import com.how2codex.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.how2codex.handler;
import com.how2codex.data.ServiceRequest;
public interface SupportServiceItf
{
    public void handleRequest(ServiceRequest request);
}

SupportService.java

package com.how2codex.handler;
import com.how2codex.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.how2codex.handler;
import com.how2codex.ServiceLevel;
import com.how2codex.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.how2codex.handler;
import com.how2codex.ServiceLevel;
import com.how2codex.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.how2codex.handler;
import com.how2codex.ServiceLevel;
import com.how2codex.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.how2codex.handler;
import com.how2codex.ServiceLevel;
import com.how2codex.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"?>
    <bean id="supportService" class="com.how2codex.handler.SupportService">
        <property name="handler" ref="frontDeskSupport"></property>
    </bean>
    <bean id="frontDeskSupport" class="com.how2codex.handler.FrontDeskSupport">
        <property name="next" ref="supervisorSupport"></property>
    </bean>
    <bean id="supervisorSupport" class="com.how2codex.handler.SupervisorSupport">
        <property name="next" ref="managerSupport"></property>
    </bean>
    <bean id="managerSupport" class="com.how2codex.handler.ManagerSupport">
        <property name="next" ref="directorSupport"></property>
    </bean>
    <bean id="directorSupport" class="com.how2codex.handler.DirectorSupport"></bean>
</beans>

测试应用

我将在链下传递各种级别的支持请求,这些请求将由正确的级别处理。任何无效的请求将按计划被拒绝。

package com.how2codex;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.how2codex.data.ServiceRequest;
import com.how2codex.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中的参考实现

doFilter每当客户端对链末尾的资源提出请求时,每次通过链传递请求/响应对时,容器都会调用Filter 的方法。传入此方法的FilterChain允许Filter将请求和响应传递给链中的下一个实体。

如果当前为给定消息级别启用了记录器,则将给定消息转发到所有已注册的输出Handler对象。

我希望这篇文章能为您对责任链模式的理解增加一些知识。如有任何疑问,请发表评论。

saigon has written 1440 articles

One thought on “责任链设计模式

Leave a Reply