类别:行为型设计模式
目的:将为了达成共同目标的一系列具有逻辑顺序的操作进行解耦
完整代码参考:https://1drv.ms/u/s!AquRvPzqx59Ri3IZYwf83oLFp6Pu?e=i6yxH7
典型场景
为一个web请求定义的一些列操作,比如
- 用户登陆验证
- 处理业务逻辑
- 压缩响应数据
注意以上3个操作是顺序的,需要登陆成功后再执行业务逻辑,业务逻辑生成响应数据后,才需要压缩响应数据
构造一个简单的http请求对象备用,参考:
public class HttpRequest {
private String username;
private String password;
public HttpRequest(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}
硬编码
1 . 用户登陆认证
public class Authenticator {
public boolean doHandle(HttpRequest request) {
var isValid = (request.getUsername() == "admin" &&
request.getPassword() == "1234");
System.out.println("Authentication");
return !isValid;
}
}
2 . 处理业务逻辑
public class BusinessLogic {
public boolean doHandle(HttpRequest request) {
System.out.println("Log");
return false;
}
}
3 . 压缩响应数据
public class Compressor {
public boolean doHandle(HttpRequest request) {
System.out.println("Compress");
return false;
}
}
很容易写出下面的流程处理代码:
var request = new HttpRequest("root", "root");
var auth = new Authenticator();
var businessLogic = new BusinessLogic();
var compressor = new Compressor();
if (!auth.doHandle(request)) {
if (!businessLogic.doHandle(request)) {
compressor.doHandle(request);
} else {
// 处理结束
}
} else {
// 处理结束
}
可以看到随着处理步骤的增加,上面代码的混乱程度会越来越验证,特别是对于处理http请求这种步骤可能多达2、30个的复杂流程来说,这块代码将变得很难维护
模式实现
责任链的解决方式是,在每个流程处理class中持有下个处理流程的引用,通过判断当前流程是否成功,来决定是否调用下个处理流程
代码
每个流程持有的下个流程的引用、以及判断是否调用下个流程的代码实现可以放到处理流程的父类中,参考 Handler.java
public abstract class Handler {
private Handler next;
public Handler(Handler next) {
this.next = next;
}
public void handle(HttpRequest request) {
if (doHandle(request))
return;
if (next != null)
next.handle(request);
}
public abstract boolean doHandle(HttpRequest request);
}
对下个流程的引用通过构造函数传递进来,通过调用hand()方法间接调用当前流程doHandle方法进行流程处理
所有的流程处理类继承这个Handler即可,拿BusinessLogic举例,参考:
public class BusinessLogic extends Handler {
public BusinessLogic(Handler next) {
super(next);
}
@Override
public boolean doHandle(HttpRequest request) {
System.out.println("Log");
return false;
}
}
然后依次处理Authenticator.java、Compressor.java
然后创建和使用这些流程
var compressor = new Compressor(null);
var businessLogic = new BusinessLogic(compressor);
var authenticator = new Authenticator(businessLogic);
var httpRequest = new HttpRequest("root", "root");
authenticator.handle(httpRequest);
可以看到把if判断的逻辑代码分散到了各自的流程处理类中,主流程更清晰了
UML
为什么责任链模式更好
- 分解逻辑判断的复杂度
- 使用者可以灵活选择不同的处理流程、调整处理顺序
- 新流程非常容易加入(集成Handler类即可)
一些注意的点
流程处理方法doHandle中返回值表示流程处理是否结束,true表示结束,false表示未结束,返回true后就不需要再执行下面的流程了