概念:
责任链模式是一种行为设计模式,它允许多个对象都有机会处理请求,而不是将请求发送给一个处理者。每个处理者都包含对下一个处理者的引用,形成一个链条。请求沿着这条链传递,直到有一个处理者处理它为止。
使用场景:
- 多个对象可以处理同一请求: 当一个请求可以被多个对象中的一个处理,而不确定哪个对象会处理,就可以使用责任链模式。
- 请求的发送者和接收者解耦: 发送者不需要知道处理请求的具体对象,只需将请求发送给第一个处理者。接收者也不需要知道请求的发送者是谁,只需处理请求即可。
- 动态组合处理者: 可以动态地组合和拆解处理者链。通过增加或移除处理者,可以灵活地调整系统的处理流程。
- 避免请求发送者与接收者耦合: 请求发送者无需知道处理请求的具体处理者,从而降低了系统的耦合度。
- 处理请求的对象集合可能会变动: 处理者链可以动态地调整,适用于对象集合可能变动的情况。
缺点:
- 性能问题: 因为责任链的请求可能被多个处理者依次处理,直到找到合适的处理者为止,可能会导致一定的性能开销。
- 请求可能无法被处理: 如果责任链没有被正确配置,或者存在漏洞,可能导致请求无法被处理。
- 可能过于灵活: 过度使用责任链模式可能导致系统变得过于灵活,难以理解和维护。
建议:
其实看了以上缺点之后我们可以发现,对于一些不必要的场景我们尽量还是不要去使用责任链模式来给系统增加复杂度,对于后期接手项目的同学是相当的难以维护及理解,当然这里的同学指的是像我这种菜鸡程序员。
案例Demo:
下面我就基于请求参数处理的需求来实现一个简单的Spingboot下开发的一个Demo案例,我处理过程中是对对象中的参数count进行规则判断进行加减
第一步是先创建出责任链处理的接口和请求参数实体对象
java
/**责任链节点的接口
* @Author duJi
* @Date 2023/12/06
*/
public interface Handler {
/**
* 节点处理请求接口
* @param request
*/
void handleRequest(HandlerRequest request);
/**
* 设置下一个节点处理者
* @param nextHandler
*/
void setNextHandler(Handler nextHandler);
}
java
/** 请求参数实体
* @Author duJi
* @Date 2023/12/06
*/
public class HandlerRequest {
private Integer count;
public HandlerRequest(Integer count) {
this.count = count;
}
public HandlerRequest() {
}
public Integer getCount() {
return count;
}
public void setContent(Integer count) {
this.count = count;
}
}
第二步则是根据业务去定义相对应的处理接口实现类
java
@Slf4j
public class FirstHandler implements Handler {
private Handler handler;
@Override
public void handleRequest(HandlerRequest request) {
//自身业务处理
log.info("first handler");
if (request.getCount() <= 2) {
request.setContent(request.getCount() + 1);
}
//判断是否有下一处理节点
if (Objects.nonNull(handler)){
log.info("next handler");
handler.handleRequest(request);
}
}
@Override
public void setNextHandler(Handler nextHandler) {
this.handler = nextHandler;
}
}
java
@Slf4j
public class SecondHandler implements Handler {
private Handler handler;
@Override
public void handleRequest(HandlerRequest request) {
//自身业务处理
log.info("second handler");
if (request.getCount() > 2) {
request.setContent(request.getCount() + 1);
}
//判断是否有下一处理节点
if (Objects.nonNull(handler)){
log.info("next handler");
handler.handleRequest(request);
}
}
@Override
public void setNextHandler(Handler nextHandler) {
this.handler = nextHandler;
}
}
java
@Slf4j
public class ThirdHandler implements Handler {
private Handler handler;
@Override
public void handleRequest(HandlerRequest request) {
//自身业务处理
log.info("third handler");
if (request.getCount() < 5) {
request.setContent(request.getCount() - 1);
}
//判断是否有下一处理节点
if (Objects.nonNull(handler)){
log.info("next handler");
handler.handleRequest(request);
}
}
@Override
public void setNextHandler(Handler nextHandler) {
this.handler = nextHandler;
}
}
第三步便是最关键的一步,编写责任链配置中心去管理我们需要的处理规则实现类
java
/**责任链配置管理中心
* @Author duJi
* @Date 2023/12/06
*/
@Configuration
public class ChainConfig {
@Bean
public Handler chain() {
FirstHandler firstHandler = new FirstHandler();
SecondHandler secondHandler = new SecondHandler();
ThirdHandler thirdHandler = new ThirdHandler();
//这里填写顺序没有强制要求
firstHandler.setNextHandler(secondHandler);
secondHandler.setNextHandler(thirdHandler);
return firstHandler;
}
}
最后便是我们的测试接口了
java
/** 责任链测试接口
* @Author duJi
* @Date 2023/12/06
*/
@Slf4j
@RestController
@Api(tags = "责任链测试接口")
@RequestMapping("/responsibility")
public class HandlerController {
@Resource
private Handler handler;
@ApiOperation("测试接口")
@GetMapping("/test")
public void handleRequest(){
HandlerRequest request = new HandlerRequest(1);
handler.handleRequest(request);
log.info("success , count : "+request.getCount());
}
}
测试结果
注意
这里测试结果是没问题的,这里需要大家注意下,我的这个Demo里的handler实现是在配置中心中手动new创建出来的,并不是利用spring相关注解进行实例化,所以大家参考的时候要注意,如果在上面加上spring的@Service
等注解,项目会无法启动,报错信息是发现多个handler实例。
这里欢迎大家对我提出宝贵的建议,我自身对这个责任链模式的使用并不是很熟练,也没有在项目中实践过,如果大家有更好的案例欢迎评论出来,我会去学习的!