责任链设计模式

位置:首页>文章>详情   分类: Java教程 > 编程技术   阅读(251)   2023-06-26 07:54:18

责任链被称为行为模式。这种模式的主要目标是避免将请求的发送者与接收者耦合,从而为多个对象提供处理请求的机会。 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 :请求的发起者,这将访问处理程序来处理它。

participants_of_chain_of_responsibility-4978976

要解决的示例问题

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

建议的解决方案

上述问题很适合使用责任链模式。我们可以定义每个级别的处理程序,即支持台、主管、经理和主管。然后我们可以定义一个链来处理支持请求。此链必须遵循以下顺序:

Support desk > supervisor > manager > director

上面的链也可以使用 java 中的编程解决方案来管理,但在本教程中,我使用 spring 来注入依赖项,从而形成这个链。此外,系统将首先将请求分配给前台。

参与者类图

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

chainofresponsibility_classdiagram-2377740

参与者的源代码

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

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

要下载上述示例应用程序的源代码,请单击以下链接。

JDK 中的参考实现

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

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

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

快乐学习!!

地址:https://www.cundage.com/article/chain-of-responsibility-design-pattern.html

相关阅读

Bridge design pattern 用于将一个类解耦为两个部分——抽象和它的实现——这样两者可以在未来发展而不会相互影响。它增加了类抽象与其实现之间的松散耦合。 将抽象与其实现分离,以便...
设计模式是用来解决出现问题的一种模式,大家都知道吧?我们还知道,行为设计模式 是识别对象之间常见通信模式的设计模式。其中一种行为模式是访问者模式,我们将在本文中了解它。 如果您一直在处理管理大量...
Camel Design Patterns 本书包含 20 种模式和大量的设计技术和最佳实践< span style="font-weight: 400;"&gtl;Apache Came...
学习将正则表达式编译成java.util.function.Predicate。当您想对匹配的标记执行某些操作时,这会很有用。 将正则表达式转换为谓词 我有不同域的电子邮件列表,我只想对域名为“...
根据 GoF 的定义,中介者模式 定义了一个对象 封装一组对象如何交互。调解器通过防止对象相互显式引用来促进松散耦合,它让我们可以独立地改变它们的交互。 Mediator 是一种行为设计模式,也...
命令模式 是一种行为设计模式,有助于将业务逻辑抽象为离散的操作,我们称之为命令。此命令对象有助于两个类之间的松散耦合,其中一个类(调用者)应调用另一个类(接收者)上的方法来执行业务操作。 让我们...
在java中创建类实例的最常用方法是什么?大多数人会回答这个问题:“使用新关键字”。好吧,它现在被认为是过时的。看看怎么样?? 如果对象创建代码散布在整个应用程序中,并且如果您需要更改对象创建过...
根据 GoF 的定义,迭代器模式 提供了一种在不暴露其底层表示的情况下按顺序访问聚合对象元素的方法。它是行为设计模式。 顾名思义,迭代器有助于以定义的方式遍历对象集合,这对客户端应用程序很有用。...
Memento 设计模式是行为模式,是四人帮讨论的 23 种设计模式之一。 Memento 模式 用于将对象的状态恢复到以前的状态。它也被称为快照模式。 备忘录就像对象生命周期中的还原点,客户端...
根据 GoF 的定义,观察者模式定义了对象之间的一对多依赖关系,这样当一个对象改变状态时,它的所有依赖对象都会得到通知并自动更新。它也称为发布-订阅模式。 在观察者模式中,有许多观察者(订阅者对...