目录
一、基础概念
二、UML类图
三、角色设计
四、案例分析
4.1、在Java中实现
4.2、在SpringBoot中实现
五、总结
一、基础概念
责任链模式是一种行为设计模式,它允许你将请求沿着处理者链进行发送。请求会被链上每个处理者处理,直到请求被处理完毕。该模式主要解决的是请求的发送者和多个请求处理者之间建立一条链式的调用关系,以实现请求的逐层解析处理。
二、UML类图
三、角色设计
角色 | 描述 |
---|---|
抽象处理者角色 | 定义了请求处理的接口,提供责任传递机制 |
具体处理者角色 | 实现了抽象处理者的处理方法,对请求进行处理 |
客户端角色 | 创建处理链,并向链头发送请求,不直接访问处理者 |
四、案例分析
下面我们利用责任链模式实现一个可扩展的请假审批流程,通过链式传递请求实现请求者和处理者的解耦,不需要知道整个链的结构。
4.1、在Java中实现
定义了抽象处理者类Handler,里面有一个successor表示下一级处理者,代码如下:
public abstract class Handler {
protected Handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract void handleRequest(int leaveDays);
}
Manager、Director、Boss继承了Handler,分别代表不同级别的审批人,在每个具体处理者中判断请假天数,如果在权限内就审批通过,否则传给下一级处理者。
public class Manager extends Handler {
@Override
public void handleRequest(int leaveDays) {
if (leaveDays <= 3) {
System.out.println("请假" + leaveDays + "天,主管审批通过!");
} else {
successor.handleRequest(leaveDays);
}
}
}
public class Director extends Handler {
@Override
public void handleRequest(int leaveDays) {
if (leaveDays <= 6) {
System.out.println("请假" + leaveDays + "天,经理审批通过!");
} else {
successor.handleRequest(leaveDays);
}
}
}
public class Boss extends Handler {
@Override
public void handleRequest(int leaveDays) {
if (leaveDays <= 10) {
System.out.println("请假" + leaveDays + "天,老板审批通过!");
} else {
System.out.println("请假" + leaveDays + "天,老板审批不通过!");
}
}
}
将三个处理者链成一条责任链,并依次发起请假请求,请求会从Manager开始,依次传递到Director和Boss,直到有人审批通过或最终审批不通过。
客户端:
public class Client {
public static void main(String[] args) {
//主管
Handler manager = new Manager();
//经理
Handler director = new Director();
//老板
Handler boss = new Boss();
manager.setSuccessor(director);
director.setSuccessor(boss);
manager.handleRequest(1);
manager.handleRequest(4);
manager.handleRequest(8);
manager.handleRequest(12);
}
}
运行结果如下:
4.2、在SpringBoot中实现
先定义一个Handler接口,包含处理请求的方法handleRequest,参数为请假天数leaveDays。
package com.example.zrl.service;
public interface Handler {
public boolean handleRequest(int leaveDays);
}
定义Manager类实现Handler接口,表示主管审批角色。在handleRequest方法中,如果天数<=3,则输出审批通过信息,这是主管的审批规则。
注:@Order是指定Bean的加载顺序,数字越小越先被加载!
package com.example.zrl.service;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(0)
public class Manager implements Handler {
@Override
public boolean handleRequest(int leaveDays) {
if (leaveDays <= 3) {
System.out.println("请假" + leaveDays + "天,主管审批通过!");
return false;
}
return true;
}
}
定义Director类实现Handler接口,表示经理审批角色。在handleRequest方法中,如果天数<=6,则输出审批通过信息,这是经理的审批规则。
package com.example.zrl.service;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(1)
public class Director implements Handler {
@Override
public boolean handleRequest(int leaveDays) {
if (leaveDays <= 6) {
System.out.println("请假" + leaveDays + "天,经理审批通过!");
return false;
}
return true;
}
}
定义Boss类实现Handler接口,表示老板审批角色。在handleRequest方法中,如果天数<=10,则输出审批通过信息,如果天数>10则输出不通过,这是老板的审批规则。
package com.example.zrl.service;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(2)
public class Boss implements Handler {
@Override
public boolean handleRequest(int leaveDays) {
if (leaveDays <= 10) {
System.out.println("请假" + leaveDays + "天,老板审批通过!");
} else {
System.out.println("请假" + leaveDays + "天,老板审批不通过!");
}
return false;
}
}
定义HandlerService类,注入实现了Handler接口的bean列表,在handle方法中遍历这个列表,调用每个Handler的handleRequest方法,模拟流转。
package com.example.zrl.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class HandlerService {
@Autowired
private List<Handler> handlerList;
public void handle(int leaveDays){
for(Handler handler : handlerList){
boolean flag = handler.handleRequest(leaveDays);
if(!flag){
break;
}
}
}
}
单元测试:
package com.example.zrl;
import com.example.zrl.service.HandlerService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ZrlApplicationTests {
@Autowired
private HandlerService handlerService;
@Test
void contextLoads() {
handlerService.handle(2);
handlerService.handle(5);
handlerService.handle(9);
handlerService.handle(15);
}
}
运行结果如下:
五、总结
优点:
1、降低了请求发送者和接收者之间的耦合关系。sender只需要知道chain,不必知道chain中的具体的handler。
2、增强了系统的可扩展性。可以动态地在链中增加或者删除处理者,来满足不同的处理需求。
3、简化了对象间的连接。sender仅需维持一个指向chain对象的引用,chain对象会自行维护对真正处理者的引用。
4、责任链上的处理者负责处理请求,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
5、可以理解为财务审批流程,一个请求需要层层审批,可以通过责任链来实现。
缺点:
1、不能保证请求一定被接收。由于一个请求没有明确的接收者,所以不能保证它一定会被处理。
2、请求可能需要遍历整个链才能找到合适的处理者,影响效率。
3、调试不方便。较长的链条可能会使调试变得困难。
4、如果责任链比较长,性能会受到一定影响。
5、处理者必须知道链的结构和组成。
应用场景:
1、多级请求处理
将请求的处理分发给一个处理链,让请求依序经过整个链中的处理器,如购买订单的批准流程。
2、异常处理
将异常处理委托给责任链,按顺序查找能够处理该异常的处理器。
3、Servlet过滤器
在Servlet中,可以使用过滤器链对请求进行过滤和处理。
4、Logging filters
日志框架允许定义日志过滤器链,过滤和处理不同优先级的日志请求。
5、前端拦截器
在Vue、Angular等框架中,使用拦截器链对请求进行拦截处理。
6、Spring AOP
Spring AOP的拦截器链也是一种应用责任链模式的例子。
7、J2EE过滤器
在J2EE的Web应用中,过滤器(Filter)经常以链的形式应用。
符合的设计原则:
1、单一职责原则(Single Responsibility Principle)
责任链上的每个处理器只需要关注自身的逻辑,不需要关心链的其它部分。
2、开闭原则(Open Closed Principle)
可以通过添加新的处理器来扩展责任链,而无需修改现有代码。
3、组合复用原则(Composite Reuse Principle)
链中的处理器可以通过组合的方式产生新的对象,而请求的发送者只与链作为一个整体进行交互。
4、依赖倒置原则(Dependency Inversion Principle)
请求的发送者依赖抽象的链对象,而不是具体的处理器对象。
5、迪米特法则(Law of Demeter)文章来源:https://www.toymoban.com/news/detail-555333.html
每个处理器只与它的后继者交互,而不需要知道链的全貌。文章来源地址https://www.toymoban.com/news/detail-555333.html
到了这里,关于Java设计模式之行为型-责任链模式(UML类图+案例分析)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!