介绍
责任链模式是将每一个节点看作一个对象,每个节点处理的请求均不同,且节点内部维护下一个节点对象。当请求进来时,从首端进入,沿着链的路径依次传递给每一个节点对象,直到有对象处理这个请求位置。
责任链模式主要是解耦了请求与处理,客户只需要将请求发送到链上即可,无需关心请求的具体内容和处理细节,请求会自动进行传递直至有节点对象进行处理。
适用场景:
- 多个对象可以处理同一个请求,但是具体由哪个对象处理则在运行时决定。
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 可动态指定一组对象处理请求。
责任链模式中几个重要的角色:
- 抽象处理类:定义请求处理的方法,并维护下一个处理节点引用。
- 具体处理:对请求进行处理,如果不归本类管,则进行转发。
实战
接下来我们运用责任链模式来做一个登录验证的流程demo。
顶层定义
package handlerChain;
/**
* @author chengyanqi
* @date 2021/8/18 22:45
*/
public abstract class Handler {
protected Handler chain;
public void next(Handler handler) {
this.chain = handler;
}
public abstract void doHandler(User user);
public static class Builder{
private Handler head;
private Handler tail;
public Builder addHandler(Handler handler) {
if (this.head == null) {
this.head = this.tail = handler;
return this;
}
this.tail.next(handler);
this.tail = handler;
return this;
}
public Handler build() {
return this.head;
}
}
}
责任链各个节点的具体实现
package handlerChain;
import org.springframework.util.StringUtils;
/**
* @author chengyanqi
* @date 2021/8/18 22:51
*/
public class ValidateHandler extends Handler {
@Override
public void doHandler(User user) {
if (StringUtils.isEmpty(user.getUserName()) || StringUtils.isEmpty(user.getPassword())) {
System.out.println(user.getUserName() + "用户名密码为空!");
return;
}
System.out.println(user.getUserName() + "用户名密码校验成功往下执行~");
chain.doHandler(user);
}
}
package handlerChain;
/**
* @author chengyanqi
* @date 2021/8/18 23:05
*/
public class LoginHandler extends Handler {
@Override
public void doHandler(User user) {
if (!user.getPassword().equals("password")) {
System.out.println(user.getUserName() + "密码校验失败!");
return;
}
System.out.println(user.getUserName() + "登录成功~");
chain.doHandler(user);
}
}
package handlerChain;
/**
* @author chengyanqi
* @date 2021/8/18 23:07
*/
public class AuthHandler extends Handler {
@Override
public void doHandler(User user) {
if (!"管理员".equals(user.getRoleName())) {
System.out.println(user.getUserName() + "没有操作权限!");
return;
}
System.out.println(user.getUserName() + "操作成功!");
}
}
构建责任链业务代码
package handlerChain;
/**
* @author chengyanqi
* @date 2021/8/18 23:39
*/
public class UserHandlerChain {
public void login(String userName, String password, String roleName) {
Handler.Builder builder = new Handler.Builder();
builder.addHandler(new ValidateHandler())
.addHandler(new LoginHandler())
.addHandler(new AuthHandler());
builder.build().doHandler(new User(userName, password, roleName));
}
}
测试
package handlerChain;
/**
* @author chengyanqi
* @date 2021/8/18 23:45
*/
public class Test {
public static void main(String[] args) {
UserHandlerChain chain = new UserHandlerChain();
chain.login("张三", "pasword", "管理员");
chain.login("李四", "password", "管理员2");
chain.login("王五", "password", "管理员");
}
}
张三用户名密码校验成功往下执行~
张三密码校验失败!
李四用户名密码校验成功往下执行~
李四登录成功~
李四没有操作权限!
王五用户名密码校验成功往下执行~
王五登录成功~
王五操作成功!