一.介绍
责任链模式(Chain of Responsibility Pattern)属于行为型模式。该模式为请求创建了一个接收者对象的链,链中的每一个节点处理自己范围内的逻辑,如果一个节点不能处理该请求,那么它会把相同的请求传给下一个节点,依此类推。本文介绍自关联和非自关联两种实现方式
二.场景约束
客户端请求要在通过请求频率校验、登录认证、访问权限校验后,才能执行接下来的业务逻辑
三.UML类图
自关联
节点本身维护下一个节点
非自关联
采用ArrayList维护整个链条
四.自关联示意代码
//抽象处理者
public abstract class Handler {
protected Handler next;
public Handler setNext(Handler next) {
this.next = next;
return next;
}
protected abstract boolean handleRequest(String request);
}
//具体处理者
class FrequentHandler extends Handler {
@Override
protected boolean handleRequest(String request) {
if (request.contains("请求频率通过")) {
System.out.println("请求频率通过");
if(next == null){
return true;
}else{
return next.handleRequest(request);
}
} else {
System.out.println("请求频率不通过");
return false;
}
}
}
//具体处理者
class LoginHandler extends Handler {
@Override
protected boolean handleRequest(String request) {
if (request.contains("登录认证通过")) {
System.out.println("登录认证通过");
if(next == null){
return true;
}else{
return next.handleRequest(request);
}
} else {
System.out.println("登录认证不通过");
return false;
}
}
}
//具体处理者
class PermissionHandler extends Handler {
@Override
protected boolean handleRequest(String request) {
if (request.contains("访问权限通过")) {
System.out.println("访问权限通过");
if(next == null){
return true;
}else{
return next.handleRequest(request);
}
} else {
System.out.println("访问权限不通过");
return false;
}
}
}
客户端
public class Client {
public static void main(String[] args) {
Handler frequentHandler = new FrequentHandler();
Handler loginHandler = new LoginHandler();
Handler permissionHandler = new PermissionHandler();
frequentHandler.setNext(loginHandler).setNext(permissionHandler);
frequentHandler.handleRequest("请求频率通过登录认证通过访问权限通过");
}
}
五.非自关联示意代码
非自关联可以实现链条的嵌套
//抽象处理者
public abstract class Handler {
protected abstract boolean handleRequest(String request);
}
//具体处理者
class FrequentHandler extends Handler {
@Override
protected boolean handleRequest(String request) {
if(request.contains("请求频率通过")){
System.out.println("请求频率通过");
return true;
}else{
System.out.println("请求频率不通过");
return false;
}
}
}
//具体处理者
class LoginHandler extends Handler {
@Override
protected boolean handleRequest(String request) {
if(request.contains("登录认证通过")){
System.out.println("登录认证通过");
return true;
}else{
System.out.println("登录认证不通过");
return false;
}
}
}
//具体处理者
class PermissionHandler extends Handler {
@Override
protected boolean handleRequest(String request) {
if(request.contains("访问权限通过")){
System.out.println("访问权限通过");
return true;
}else{
System.out.println("访问权限不通过");
return false;
}
}
}
class HandlerChain extends Handler {
private final List<Handler> handlers = new ArrayList<>();
public HandlerChain addHandler(Handler handler) {
handlers.add(handler);
return this;
}
@Override
protected boolean handleRequest(String request) {
for (Handler handler : handlers) {
if(!handler.handleRequest(request)) return false;
}
return true;
}
}
客户端
public class Client {
public static void main(String[] args) {
HandlerChain handlerChain1 = new HandlerChain();
handlerChain1.addHandler(new FrequentHandler()).addHandler(new LoginHandler());
HandlerChain handlerChain2 = new HandlerChain();
handlerChain2.addHandler(new PermissionHandler());
//链条嵌套
handlerChain1.addHandler(handlerChain2);
handlerChain1.handleRequest("请求频率通过登录认证通过访问权限通过");
}
}
六.意图
- 责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递和被处理
- 责任链模式的独到之处是将其节点处理组合成了链式结构,并允许节点自身决定是否进行请求处理或转发,相当于让请求流动起来
七.优缺点
- 优点
- 降低耦合:一个对象无需了解谁处理它,也不需要关心处理过程
- 符合单一职责原则:每个处理类只实现一个明确的处理逻辑
- 符合开闭原则:可以很方便的增减处理类
- 缺点
- 只能顺序执行,可能会有性能问题
- 具体处理类可以自行结束处理链,不能确保每个接收者都会执行
八.模拟Filter
Filter正序处理request,逆序处理response,那么如何实现呢
主要步骤
- 在处理request和response之间调用下一个节点的处理方法
- 成员变量pos记录节点索引
- 将链条本身也当作参数传递
业务代码
//抽象处理者
public abstract class Filter {
protected abstract void handleRequest(Request request, Response response, FilterChain filterChain);
}
//具体处理者
class FrequentFilter extends Filter {
@Override
protected void handleRequest(Request request, Response response, FilterChain filterChain) {
if (request.message.contains("请求频率通过")) {
System.out.println("请求频率通过");
filterChain.handleRequest(request, response);
if (response.message.contains("请求频率通过")) {
System.out.println("请求频率通过");
} else {
System.out.println("请求频率不通过");
}
} else {
System.out.println("请求频率不通过");
}
}
}
//具体处理者
class LoginFilter extends Filter {
@Override
protected void handleRequest(Request request, Response response, FilterChain filterChain) {
if (request.message.contains("登录认证通过")) {
System.out.println("登录认证通过");
filterChain.handleRequest(request, response);
if (response.message.contains("登录认证通过")) {
System.out.println("登录认证通过");
} else {
System.out.println("登录认证不通过");
}
} else {
System.out.println("登录认证不通过");
}
}
}
//具体处理者
class PermissionFilter extends Filter {
@Override
protected void handleRequest(Request request, Response response, FilterChain filterChain) {
if (request.message.contains("访问权限通过")) {
System.out.println("访问权限通过");
filterChain.handleRequest(request, response);
if (response.message.contains("访问权限通过")) {
System.out.println("访问权限通过");
} else {
System.out.println("访问权限不通过");
}
} else {
System.out.println("访问权限不通过");
}
}
}
class FilterChain{
private final List<Filter> filters = new ArrayList<>();
//记录位置
private int pos = 0;
public FilterChain addFilter(Filter filter) {
filters.add(filter);
return this;
}
public void handleRequest(Request request, Response response) {
if (pos < filters.size()) {
filters.get(pos++).handleRequest(request, response, this);
}
}
}
//请求
class Request {
public String message;
public Request(String message) {
this.message = message;
}
}
//响应
class Response {
public String message;
public Response(String message) {
this.message = message;
}
}
客户端
public class Client {
public static void main(String[] args) {
FilterChain filterChain = new FilterChain();
filterChain.addFilter(new FrequentFilter()).addFilter(new LoginFilter()).addFilter(new PermissionFilter());
Request request = new Request("请求频率通过登录认证通过访问权限通过");
Response response = new Response("请求频率通过登录认证不通过访问权限通过");
filterChain.handleRequest(request, response);
}
}
九.在Filter中的实际应用
感兴趣的可以研究tomcat的org.apache.catalina.core.ApplicationFilterChain