设计模式-责任链模式(Chain of Responsibility)

2023-11-10 08:05

本文主要是介绍设计模式-责任链模式(Chain of Responsibility),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

设计模式-责任链模式(Chain of Responsibility)

    • 一、责任链模式概述
      • 1.1 什么是责任链模式
      • 1.2 简单实现责任链模式
      • 1.3 使用责任链模式的注意事项
    • 二、责任链模式的用途
    • 三、责任链模式实现方式
      • 3.1 基于接口实现责任链模式
      • 3.2 基于抽象类实现责任链模式
      • 3.3 基于匿名内部类实现责任链模式
      • 3.4 基于Lambda表达式实现责任链模式

一、责任链模式概述

1.1 什么是责任链模式

责任链模式是一种面向对象设计模式,该模式中包含了一系列处理对象和命令对象。每个处理对象都有能力决定自己可以处理哪些命令对象,如果遇到无法处理的命令对象,它会将请求传递给下一个处理对象。这种模式的核心在于避免请求发送者与接收者之间的紧密耦合,让多个对象都有可能接收请求,并将这些对象连接成一条链,沿着这条链传递请求,直到有对象处理它为止。

以公司员工请假为例,员工的请假请求可能有多个领导可以批准,但每个领导的批准权限不同。员工需要根据自己要请假的天数去找对应的领导签名。这就是责任链模式的一个生动实例。其实现过程就如同“击鼓传花”游戏,每个参与者都有机会处理事件,但如果无法处理则继续传给下一个人。

在开发中,责任链模式常用于处理复杂数据处理和校验的场景。通过使用责任链模式,可以将一个请求的处理过程分解为一系列的处理对象,使得代码更加清晰、灵活和易于维护。

1.2 简单实现责任链模式

首先,我们定义一个抽象的处理类(Handler):

public abstract class Handler {protected Handler nextHandler;public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}public abstract void handleRequest(String request);
}

然后,我们创建具体的处理类(ConcreteHandler),它们继承自抽象的处理类,并实现了handleRequest方法:

public class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(String request) {if (request.equals("A")) {System.out.println("ConcreteHandlerA处理了请求:" + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("没有处理器可以处理该请求:" + request);}}
}public class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(String request) {if (request.equals("B")) {System.out.println("ConcreteHandlerB处理了请求:" + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("没有处理器可以处理该请求:" + request);}}
}

然后,我们创建具体的处理类(ConcreteHandler),它们继承自抽象的处理类,并实现了handleRequest方法:

public class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(String request) {if (request.equals("A")) {System.out.println("ConcreteHandlerA处理了请求:" + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("没有处理器可以处理该请求:" + request);}}
}public class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(String request) {if (request.equals("B")) {System.out.println("ConcreteHandlerB处理了请求:" + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("没有处理器可以处理该请求:" + request);}}
}

最后,我们在客户端代码中创建处理器对象,并将它们连接起来:

public class Client {public static void main(String[] args) {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setNextHandler(handlerB);handlerA.handleRequest("A"); // 输出:ConcreteHandlerA处理了请求:AhandlerA.handleRequest("B"); // 输出:ConcreteHandlerB处理了请求:BhandlerA.handleRequest("C"); // 输出:没有处理器可以处理该请求:C}
}

这样,我们就实现了一个简单的责任链模式。当客户端发送一个请求时,它会沿着责任链传递,直到找到一个可以处理该请求的处理器。

1.3 使用责任链模式的注意事项

  • 1、存在循环调用的风险。在实现责任链模式时,可能存在节点之间的循环调用,从而形成死循环。这种循环调用的风险通常出现在两种情况下:一是责任链节点自身会对请求进行多次处理;二是责任链节点之间相互调用。为了避免这种情况,需要对责任链节点的处理逻辑进行严格的控制和规范,确保节点的处理逻辑只能一次性地对请求进行处理,并且不会出现相互调用的情况。另外,可以通过设置最大处理次数或者设置超时时间等机制来防止出现死循环,从而避免对系统的影响。

  • 2、确定责任链的顶端和底端。在实现责任链模式时,需要确定责任链的顶端和底端,以确保请求能够被正确地传递和处理。

  • 3、避免请求发送者与接收者之间的紧密耦合关系。在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,这样可以降低系统的耦合度。

  • 4、注意性能问题。由于每个处理器都需要处理请求和传递请求,因此使用责任链模式可能会导致系统性能下降。为了解决这个问题,可以考虑使用异步处理等方式来提高系统的性能。

二、责任链模式的用途

责任链模式主要用于处理那些需要经过多个处理步骤或处理者才能完成的请求。其主要应用场景包括:

  • 1、过滤器模式:例如在Java Web应用中,过滤器链用于对HTTP请求和响应进行处理。每个过滤器负责处理特定的任务,然后将请求传递给下一个过滤器。这种场景下,责任链模式可以有效地解耦每个过滤器的处理逻辑。

  • 2、事件处理模式:在图形用户界面编程中,事件处理通常采用责任链模式。例如在一个按钮上,可能有多个监听器(如点击、鼠标移动等),每个监听器负责处理一种特定的事件。当事件发生时,会沿着监听器链进行传递,直到有监听器处理该事件为止。

  • 3、工作流引擎:在企业级应用中,工作流引擎通常使用责任链模式来处理复杂的业务流程。每个处理节点负责处理流程中的特定步骤,然后将工作项传递给下一个处理节点。

  • 4、权限设计:在权限设计中,可以使用责任链模式来实现权限验证。例如,一个用户可能需要经过多个角色的权限验证,每个角色负责验证一部分权限。这样既可以实现权限验证的逻辑分离,又可以提高系统的灵活性和扩展性。

三、责任链模式实现方式

3.1 基于接口实现责任链模式

首先,我们需要定义一个处理请求的接口,然后创建具体的处理器类实现该接口。最后,在客户端代码中,我们将处理器对象链接在一起,形成一个责任链。

以下是一个简单的Java实现:

定义处理请求的接口:

public interface RequestHandler {void setNextHandler(RequestHandler nextHandler);void handleRequest(String request);
}

创建具体的处理器类实现该接口:

public class ConcreteHandlerA implements RequestHandler {private RequestHandler nextHandler;@Overridepublic void setNextHandler(RequestHandler nextHandler) {this.nextHandler = nextHandler;}@Overridepublic void handleRequest(String request) {if (request.startsWith("A")) {System.out.println("ConcreteHandlerA处理了请求:" + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("没有处理器可以处理该请求:" + request);}}
}public class ConcreteHandlerB implements RequestHandler {private RequestHandler nextHandler;@Overridepublic void setNextHandler(RequestHandler nextHandler) {this.nextHandler = nextHandler;}@Overridepublic void handleRequest(String request) {if (request.startsWith("B")) {System.out.println("ConcreteHandlerB处理了请求:" + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("没有处理器可以处理该请求:" + request);}}
}

在客户端代码中,将处理器对象链接在一起,形成一个责任链:

public class Client {public static void main(String[] args) {RequestHandler handlerA = new ConcreteHandlerA();RequestHandler handlerB = new ConcreteHandlerB();handlerA.setNextHandler(handlerB);handlerA.handleRequest("A1");handlerA.handleRequest("B1");handlerA.handleRequest("C1");}
}

运行客户端代码,输出结果如下:

ConcreteHandlerA处理了请求:A1
ConcreteHandlerB处理了请求:B1
没有处理器可以处理该请求:C1

3.2 基于抽象类实现责任链模式

要实现基于抽象类的责任链模式,首先需要创建一个抽象类,然后创建具体的处理器类继承自抽象类。最后在客户端代码中,将处理器对象链接在一起,形成一个责任链。以下是一个简单的示例:

创建一个抽象类Handler:

public abstract class Handler {protected Handler nextHandler;public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}public abstract void handleRequest(String request);
}

创建具体的处理器类ConcreteHandlerA和ConcreteHandlerB,分别继承自Handler:

public class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(String request) {if (request.equals("A")) {System.out.println("ConcreteHandlerA处理了请求:" + request);} else {if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("没有处理器可以处理该请求:" + request);}}}
}public class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(String request) {if (request.equals("B")) {System.out.println("ConcreteHandlerB处理了请求:" + request);} else {if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("没有处理器可以处理该请求:" + request);}}}
}

在客户端代码中,将处理器对象链接在一起,形成一个责任链:

public class Client {public static void main(String[] args) {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setNextHandler(handlerB);handlerA.handleRequest("A");handlerA.handleRequest("B");handlerA.handleRequest("C");}
}

运行客户端代码,输出结果如下:

ConcreteHandlerA处理了请求:A
ConcreteHandlerB处理了请求:B
没有处理器可以处理该请求:C

3.3 基于匿名内部类实现责任链模式

public interface Handler {void setNextHandler(Handler nextHandler);void handleRequest(String request);
}public class ConcreteHandlerA implements Handler {private Handler nextHandler;@Overridepublic void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}@Overridepublic void handleRequest(String request) {if ("A".equals(request)) {System.out.println("ConcreteHandlerA处理了请求:" + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("没有处理器可以处理该请求:" + request);}}
}public class ConcreteHandlerB implements Handler {private Handler nextHandler;@Overridepublic void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}@Overridepublic void handleRequest(String request) {if ("B".equals(request)) {System.out.println("ConcreteHandlerB处理了请求:" + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("没有处理器可以处理该请求:" + request);}}
}public class Client {public static void main(String[] args) {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setNextHandler(handlerB);handlerA.handleRequest("A");handlerA.handleRequest("B");handlerA.handleRequest("C");}
}

3.4 基于Lambda表达式实现责任链模式

责任链模式是一种行为设计模式,它允许多个对象处理一个请求,从而避免了请求的发送者和接收者之间的耦合关系。在Java中,我们可以使用Lambda表达式和接口来实现责任链模式。

首先,我们需要定义一个处理器接口,该接口包含一个处理方法:

public interface Handler {void handleRequest(String request);
}

接下来,我们可以创建具体的处理器类,实现这个接口:

public class ConcreteHandlerA implements Handler {private Handler nextHandler;@Overridepublic void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}@Overridepublic void handleRequest(String request) {if (request.equals("A")) {System.out.println("ConcreteHandlerA处理了请求:" + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("没有处理器可以处理该请求:" + request);}}
}public class ConcreteHandlerB implements Handler {private Handler nextHandler;@Overridepublic void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}@Overridepublic void handleRequest(String request) {if (request.equals("B")) {System.out.println("ConcreteHandlerB处理了请求:" + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("没有处理器可以处理该请求:" + request);}}
}

最后,我们可以使用Lambda表达式来创建处理器对象,并设置责任链:

public class Main {public static void main(String[] args) {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setNextHandler(handlerB);handlerA.handleRequest("A");handlerA.handleRequest("B");handlerA.handleRequest("C");}
}

运行上述代码,输出结果如下:

ConcreteHandlerA处理了请求:A
ConcreteHandlerB处理了请求:B
没有处理器可以处理该请求:C

这篇关于设计模式-责任链模式(Chain of Responsibility)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/381406

相关文章

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

模版方法模式template method

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/template-method 超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 上层接口有默认实现的方法和子类需要自己实现的方法

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

迭代器模式iterator

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/iterator 不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素

《x86汇编语言:从实模式到保护模式》视频来了

《x86汇编语言:从实模式到保护模式》视频来了 很多朋友留言,说我的专栏《x86汇编语言:从实模式到保护模式》写得很详细,还有的朋友希望我能写得更细,最好是覆盖全书的所有章节。 毕竟我不是作者,只有作者的解读才是最权威的。 当初我学习这本书的时候,只能靠自己摸索,网上搜不到什么好资源。 如果你正在学这本书或者汇编语言,那你有福气了。 本书作者李忠老师,以此书为蓝本,录制了全套视频。 试

利用命令模式构建高效的手游后端架构

在现代手游开发中,后端架构的设计对于支持高并发、快速迭代和复杂游戏逻辑至关重要。命令模式作为一种行为设计模式,可以有效地解耦请求的发起者与接收者,提升系统的可维护性和扩展性。本文将深入探讨如何利用命令模式构建一个强大且灵活的手游后端架构。 1. 命令模式的概念与优势 命令模式通过将请求封装为对象,使得请求的发起者和接收者之间的耦合度降低。这种模式的主要优势包括: 解耦请求发起者与处理者

springboot实战学习(1)(开发模式与环境)

目录 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 (3)前端 二、开发模式 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 Validation:做参数校验Mybatis:做数据库的操作Redis:做缓存Junit:单元测试项目部署:springboot项目部署相关的知识 (3)前端 Vite:Vue项目的脚手架Router:路由Pina:状态管理Eleme

状态模式state

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/state 在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。 在状态模式中,player.getState()获取的是player的当前状态,通常是一个实现了状态接口的对象。 onPlay()是状态模式中定义的一个方法,不同状态下(例如“正在播放”、“暂停

软件架构模式:5 分钟阅读

原文: https://orkhanscience.medium.com/software-architecture-patterns-5-mins-read-e9e3c8eb47d2 软件架构模式:5 分钟阅读 当有人潜入软件工程世界时,有一天他需要学习软件架构模式的基础知识。当我刚接触编码时,我不知道从哪里获得简要介绍现有架构模式的资源,这样它就不会太详细和混乱,而是非常抽象和易

使用Spring Boot集成Spring Data JPA和单例模式构建库存管理系统

引言 在企业级应用开发中,数据库操作是非常重要的一环。Spring Data JPA提供了一种简化的方式来进行数据库交互,它使得开发者无需编写复杂的JPA代码就可以完成常见的CRUD操作。此外,设计模式如单例模式可以帮助我们更好地管理和控制对象的创建过程,从而提高系统的性能和可维护性。本文将展示如何结合Spring Boot、Spring Data JPA以及单例模式来构建一个基本的库存管理系统