这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战
说明
定义
责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。
适用场景
- 当程序需要使用不同方式处理不同种类请求, 而且请求类型和顺序预先未知时, 可以使用责任链模式。
- 如果所需处理者及其顺序必须在运行时进行改变, 可以使用责任链模式。
- 必须按顺序执行多个处理者时, 可以使用该模式。
优点
- 你可以控制请求处理的顺序。
- 单一职责原则。 你可对发起操作和执行操作的类进行解耦。
- 开闭原则。 你可以在不更改现有代码的情况下在程序中新增处理者。
缺点
- 部分请求未被处理
- 链路太长性能受到影响
举例
- SpringMvc 拦截器设计使用了责任链模式
- Flowable工作流
代码实践
举例说明
举例实现一个登录过程中进行的各种校验,校验账号是否存在、密码是否正确、账号状态是否正常(仅仅只是举例)
代码
抽象处理类
public abstract class AbstractLoginHandler<T> {
/**
* 责任链,下一个链接节点
*/
protected AbstractLoginHandler<T> next = null;
/**
* 内部逻辑
* @param loginDTO 登录DTO
*/
public abstract String doHandler(LoginDTO loginDTO) throws Exception;
public void next(AbstractLoginHandler handler) {
this.next = handler;
}
public static class Builder<T> {
private AbstractLoginHandler<T> head;
private AbstractLoginHandler<T> tail;
public Builder<T> addHandler(AbstractLoginHandler handler) {
if (this.head == null) {
this.head = handler;
this.tail = handler;
} else {
this.tail.next(handler);
this.tail = handler;
}
return this;
}
public AbstractLoginHandler build() {
return this.head;
}
}
}
登录DTO
@Data
public class LoginDTO {
String username; //用户
String status; //状态
String password; //密码
}
具体逻辑处理:用户、密码、状态校验
/**
* @author 勤任风
* @date 2021-08-27 17:39
* 用户是否存在
*/
public class UserExistHandler extends AbstractLoginHandler {
@Override
public String doHandler(LoginDTO loginDTO) throws Exception {
String username = loginDTO.getUsername();
//验证逻辑:如果用户不存在
if(!"test_user".equals(username)){
return "用户不存在";
}
// 判断是否还有下个责任链节点,没有的话,说明已经是最后一个节点
if (next != null){
return next.doHandler(loginDTO);
}
return "验证均已通过,登录成功";
}
}
/**
* @author 勤任风
* @date 2021-08-27 17:44
* 用户状态是否正常
*/
public class UserStatusHandler extends AbstractLoginHandler {
@Override
public String doHandler(LoginDTO loginDTO) throws Exception {
String status = loginDTO.getStatus();
//验证逻辑:如果用户已被冻结
if("freeze".equals(status)){
return "账户已被冻结";
}
// 判断是否还有下个责任链节点,没有的话,说明已经是最后一个节点
if(next!=null){
return next.doHandler(loginDTO);
}
return "验证均已通过,登录成功";
}
}
/**
* @author 勤任风
* @date 2021-08-27 17:44
* 验证密码
*/
public class UserPasswordHanler extends AbstractLoginHandler {
@Override
public String doHandler(LoginDTO loginDTO) throws Exception {
String password = loginDTO.getPassword();
//验证逻辑:用户密码
if(!"123456".equals(password)){
return "密码不正确";
}
// 判断是否还有下个责任链节点,没有的话,说明已经是最后一个节点
if(next!=null){
return next.doHandler(loginDTO);
}
return "验证均已通过,登录成功";
}
}
测试Controller
@RestController
@RequestMapping("/responsibility")
public class ResponsibilityController {
/**
* 登录测试
*/
@PostMapping("/login")
public String login(@RequestBody LoginDTO loginDTO) throws Exception {
AbstractLoginHandler.Builder<Object> builder = new AbstractLoginHandler.Builder<>();
String result = builder.addHandler(new UserExistHandler())
.addHandler(new UserStatusHandler())
.addHandler(new UserPasswordHanler())
.build().doHandler(loginDTO);
return "登录结果:"+result;
}
}