Java责任链模式实战:从基础到建造者优化
本文深入解析Java中的责任链模式,针对登录验证等多级处理场景,对比原始臃肿代码与链式结构,提供从基础Handler实现到结合Builder模式自动组装链路的完整重构方案。
什么是责任链模式
责任链模式(Chain of Responsibility)是一种行为型设计模式。它将处理请求的对象连成一条链,请求沿着链传递,直到其中一个对象处理它或到达链条末尾。这种模式的核心优势在于解耦:请求的发送者无需知道具体的接收者是谁,每个节点只需判断自己是否处理,否则将请求传递给下一个节点。
其适用场景主要包括:
- 多个对象可能处理同一请求,但具体由谁处理在运行时决定。
- 不明确指定接收者的情况下,向一组对象提交请求。
根据通用UML图,该模式主要包含以下角色:
- 抽象处理者(Handler):定义处理请求的接口,并维护后继节点的引用。
- 具体处理者(Concrete Handler):实现具体逻辑,若无法处理则转发给下一节点。
应用场景:以登录流程为例
在开发管理系统时,常见的登录流程通常包含多步校验:检查参数是否为空、查询数据库验证身份、检查用户权限等。若不使用设计模式,这些逻辑往往堆砌在同一个方法中,导致代码耦合度高,违反开闭原则。
未优化前的代码问题
传统的写法是将所有判断逻辑写在一个方法里,如下所示。随着业务增长,该方法会越来越长,修改某一步骤可能需要影响整个函数,且难以测试单个校验环节。
private String login(String username, String password) {
if (username == null || password == null) {
return "账户或者密码为null";
}
User user = queryUserInfo(username, password);
if (user == null) {
return "找不到用户";
}
if (!Objects.equals(user.getRoleName(), "超管")) {
return "没有权限";
}
return "登录成功";
}
private User queryUserInfo(String username, String password) {
if (Objects.equals(username, "土豆") && Objects.equals(password, "666666")) {
return new User(username, password, "超管");
} else if (Objects.equals(username, "土豆2号") && Objects.equals(password, "666666")) {
return new User(username, password, "普通员工");
}
return null;
}
采用基础责任链模式重构
我们将不同的校验逻辑拆分为独立的“节点”,并通过 setNext 方法手动连接它们。
doHandler 接口和设置下一个节点的 setNext 方法。public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void doHandler(User user);
}
Handler,实现自己的校验逻辑,并在符合条件或校验通过后调用 this.next.doHandler(user)。public class ValidatedHandler extends Handler {
@Override
public void doHandler(User user) {
if (user.getUsername() == null || user.getPassword() == null) {
System.out.println("账户或者密码为null");
} else {
this.next.doHandler(user);
}
}
}
public class UserHandler extends Handler {
@Override
public void doHandler(User user) {
// 模拟查询用户信息并填充角色
queryUserInfo(user);
if (user.getRoleName() == null) {
System.out.println("没有找到用户");
} else {
this.next.doHandler(user);
}
}
private static void queryUserInfo(User user) {
if (Objects.equals(user.getUsername(), "土豆") && Objects.equals(user.getPassword(), "666666")) {
user.setRoleName("超管");
} else if (Objects.equals(user.getUsername(), "土豆2号") && Objects.equals(user.getPassword(), "666666")) {
user.setRoleName("普通员工");
}
}
}
public class AuthHandler extends Handler {
@Override
public void doHandler(User user) {
if (!Objects.equals(user.getRoleName(), "超管")) {
System.out.println("没有权限");
} else {
System.out.println("登入成功");
}
}
}
User user = new User("土豆", "666666");
Handler validatedHandler = new ValidatedHandler();
Handler userHandler = new UserHandler();
Handler authHandler = new AuthHandler();
// 手动连接链
validatedHandler.setNext(userHandler);
userHandler.setNext(authHandler);
// 开始执行
validatedHandler.doHandler(user);
上述 UML 图展示了使用 Builder 模式优化后的链式结构关系,此时装配逻辑被封装,调用者不再需要关心内部连接细节。
进阶:结合 Builder 模式自动化组装
虽然基础版实现了职责分离,但每次新增处理步骤都需要在调用端修改 setNext 逻辑。利用 Builder 模式可以在处理者内部自动维护链表组装,使代码更简洁。
修改 Handler 抽象类,加入内部 Builder:
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void doHandler(User user);
/**
* 引入 Builder 自动构建链路
*/
public static class Builder {
private Handler head; // 头节点
private Handler tail; // 尾节点
/**
* 添加处理节点
*/
public Builder addHandler(Handler handler) {
if (this.head == null) {
this.head = this.tail = handler;
} else {
this.tail.setNext(handler);
this.tail = handler;
}
return this;
}
/**
* 返回头节点,触发执行
*/
public Handler build() {
return this.head;
}
}
}
调用方式简化为链式调用:
User user = new User("土豆", "666666");
Handler handler = new Handler.Builder()
.addHandler(new ValidatedHandler())
.addHandler(new UserHandler())
.addHandler(new AuthHandler())
.build(); // 获取链的头节点
handler.doHandler(user); // 统一入口发起请求
优缺点分析
优点:
- 降低耦合度: 请求方只需将请求发出,无需知道哪些对象参与了处理。
- 单一职责: 每个节点只关注自己的业务逻辑。
- 符合开闭原则: 可以通过灵活增加或删除节点来改变系统行为,无需修改现有代码。
缺点:
- 性能损耗: 如果链条过长,或者存在复杂的循环引用,可能会影响性能。
- 追踪困难: 调试时较难定位请求在哪个节点中断或失败。
以上就是Java责任链模式从基础应用到高级优化的详细内容,更多关于Java设计模式的学习资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









