责任链模式介绍
责任链模式是将链中的每一个节点看成是一个对象,每个节点处理的请求不同,且内部自动维护一个下一个节点对象。当一个请求从链的首端发出时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求。属于行为型设计模式。
使用场景
责任链模式主要是解耦了请求与处理,客户端只需要将请求发送到链上即可,无需关心请求的具体内容和处理细节,请求会自动进行传递,直至有处理对象进行处理。适用于以下场景:
- 多个对象可以处理一个请求,但由哪一个对象处理,则在运行时动态决定。
- 在不明确指定接收者的情况下,向多个对象中的一个提交请求。
- 可以动态指定一组对象处理请求。
代码示例
利用责任链模式进行数据校验拦截。
抽象处理类(Handler)
结合了建造者模式
package com.example.proxy.designpatten.chain;
/**
* @author ludengke
* @title: Handler
* @projectName alibabatest
* @description: TODO
* @date 2024/6/1511:43
*/
public abstract class Handler<T> {
protected Handler chain;
public void next(Handler handler){
this.chain=handler;
}
public abstract void doHandle(Member member);
public static class Builder<T>{
private Handler<T> head;
private Handler<T> tail;
public Builder<T> addHandler(Handler<T> handler){
if (this.head==null){
this.head=this.tail=handler;
return this;
}
this.tail.next(handler);//给链中的下一个对象赋值
this.tail=handler;
return this;
}
public Handler<T> build(){
return this.head;
}
}
}
具体处理类
package com.example.proxy.designpatten.chain;
/**
* @author ludengke
* @title: AuthHandler
* @projectName alibabatest
* @description: TODO
* @date 2024/6/1511:50
*/
public class AuthHandler extends Handler{
@Override
public void doHandle(Member member) {
if (!"管理员".equals(member.getRoleName())){
System.out.println("不是管理员,没有操作权限");
return;
}
System.out.println("认证成功,往下执行");
if (this.chain!=null){
this.chain.doHandle(member);
}
}
}
package com.example.proxy.designpatten.chain;
/**
* @author ludengke
* @title: LoginHandler
* @projectName alibabatest
* @description: TODO
* @date 2024/6/1511:48
*/
public class LoginHandler extends Handler{
@Override
public void doHandle(Member member) {
System.out.println("登录成功");
member.setRoleName("管理员");
if (this.chain!=null){
this.chain.doHandle(member);
} }
}
package com.example.proxy.designpatten.chain;
import org.springframework.util.StringUtils;
/**
* @author ludengke
* @title: ValidateHandler
* @projectName alibabatest
* @description: TODO
* @date 2024/6/1511:45
*/
public class ValidateHandler extends Handler{
@Override
public void doHandle(Member member) {
if (member==null
|| StringUtils.isEmpty(member.getName())
||StringUtils.isEmpty(member.getPwd())){
System.out.println("用户或密码为空");
return;
}
System.out.println("用户密码校验成功,往下执行");
if (this.chain!=null){
this.chain.doHandle(member);
} }
}
客户端
package com.example.proxy.designpatten.chain;
/**
* @author ludengke
* @title: MemberService
* @projectName alibabatest
* @description: TODO
* @date 2024/6/1511:42
*/
public class MemberService {
public void login(String name,String pwd){
Member member=new Member();
member.setName(name);
member.setPwd(pwd);
Handler.Builder builder=new Handler.Builder();
builder.addHandler(new ValidateHandler())
.addHandler(new LoginHandler())
.addHandler(new AuthHandler());
//返回head,就是返回整个链
builder.build().doHandle(member);
}
}
测试类
package com.example.proxy.designpatten.chain;
/**
* @author ludengke
* @title: TestChain
* @projectName alibabatest
* @description: TODO
* @date 2024/6/1511:53
*/
public class TestChain {
public static void main(String[] args) {
MemberService memberService=new MemberService();
memberService.login("ss","ss");
}
}
责任链模式的优缺点
优点
- 将请求与处理解耦。
- 请求处理者(链中的节点对象)只需要关注请求的处理,对于不感兴趣的请求,转发给下个请求对象即可。
- 具备链式传递处理请求的功能,请求发送者不需要知道链路结构,只需要等待处理结果。
- 链式结构灵活,可以通过改变链的调用结构,动态增删责任。
- 易于扩展,可以加新的责任,符合开闭原则。
缺点
- 责任链太长,处理时间可能过长。
- 如果节点对象出现循环引用,可能导致死循环,使系统崩溃。