责任链模式
概念
责任链,顾名思义,就是用来处理相关事务责任的一条执行链,执行链上有多个节点,每个节点都有机会(条件匹配)处理请求事务,如果某个节点处理完了就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。
场景一
现实中,请假的OA申请:
请假天数如果是半天到1天,可能直接主管批准即可;
如果是1到3天的假期,需要部门经理批准;
如果是3天到30天,则需要总经理审批;
大于30天,正常不会批准。
类图:
员工提交请求类:LeaveRequest。
抽象的请假责任处理类:AbstractLeaveHandler。
直接主管审批处理类:DirectLeaderLeaveHandler。
部门经理处理类:DeptManagerLeaveHandler。
总经理处理类: GManagerLeaveHandler。
员工请求发起申请到抽象的责任处理类中,根据员工的请假天数,对应的处理类完成处理。 每一个责任处理类设置下面的节点。自身处理不了则传递给下一个节点处理。
代码:
LeaveRequest.java
package com.link.chain.process;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* 请假申请
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class LeaveRequest {
/**天数*/
private int leaveDays;
/**姓名*/
private String name;
}
AbstractLeaveHandler.java
package com.link.chain.process;
/**
* 请假责任链抽象处理类
*/
public class AbstractLeaveHandler {
/**
* 直接主管审批处理的请假天数
*/
protected int MIN = 1;
/**
* 部门经理处理的请假天数
*/
protected int MIDDLE = 3;
/**
* 总经理处理的请假天数
*/
protected int MAX = 30;
/**
* 领导名称
*/
protected String handlerName;
/**
* 下一个处理节点(即更高级别的领导)
*/
protected AbstractLeaveHandler nextHandler;
/**
* 设置下一节点
*/
protected void setNextHandler(AbstractLeaveHandler handler) {
this.nextHandler = handler;
}
/**
* 处理请假的请求,子类实现
*/
protected void handlerRequest(LeaveRequest request) {
}
}
DirectLeaderLeaveHandler.java
package com.link.chain.process;
/**
* 主管处理类
*/
public class DirectLeaderLeaveHandler extends AbstractLeaveHandler {
public DirectLeaderLeaveHandler(String name) {
this.handlerName = name;
}
@Override
protected void handlerRequest(LeaveRequest request) {
System.out.println("主管:" + handlerName + ",已经处理;流程结束。");
if (request.getLeaveDays() <= this.MIN) {
return;
}
if (null != this.nextHandler) {
this.nextHandler.handlerRequest(request);
} else {
System.out.println("审批拒绝!");
}
}
}
DeptManagerLeaveHandler.java
package com.link.chain.process;
/**
* 部门经理处理类
*/
public class DeptManagerLeaveHandler extends AbstractLeaveHandler {
public DeptManagerLeaveHandler(String name) {
this.handlerName = name;
}
@Override
protected void handlerRequest(LeaveRequest request) {
System.out.println("部门经理:" + handlerName + ",已经处理;流程结束。");
if (request.getLeaveDays() > this.MIN && request.getLeaveDays() <= this.MIDDLE) {
return;
}
if (null != this.nextHandler) {
this.nextHandler.handlerRequest(request);
} else {
System.out.println("审批拒绝!");
}
}
}
GManagerLeaveHandler.java
package com.link.chain.process;
/**
* 总经理处理类
*/
public class GManagerLeaveHandler extends AbstractLeaveHandler {
public GManagerLeaveHandler(String name) {
this.handlerName = name;
}
@Override
protected void handlerRequest(LeaveRequest request) {
System.out.println("总经理:" + handlerName + ",已经处理;流程结束。");
if (request.getLeaveDays() > this.MIDDLE && request.getLeaveDays() <= this.MAX) {
return;
}
if (null != this.nextHandler) {
this.nextHandler.handlerRequest(request);
} else {
System.out.println("审批拒绝!");
}
}
}
Test.java
package com.link.chain.process;
public class Test {
public static void main(String[] args) {
LeaveRequest request = LeaveRequest.builder().leaveDays(30).name("小明").build();
//直接主管
DirectLeaderLeaveHandler directLeaderLeaveHandler = new DirectLeaderLeaveHandler("陈凡");
//部门经理
DeptManagerLeaveHandler deptManagerLeaveHandler = new DeptManagerLeaveHandler("张培进");
//总经理
GManagerLeaveHandler gManagerLeaveHandler = new GManagerLeaveHandler("许顺康");
directLeaderLeaveHandler.setNextHandler(deptManagerLeaveHandler);
deptManagerLeaveHandler.setNextHandler(gManagerLeaveHandler);
directLeaderLeaveHandler.handlerRequest(request);
}
}
场景二
实现下图filter的处理顺序:
request:filter1 >> filter2
response:filter2 >> filter1
代码:
版本一:
package com.link.chain.filter.v1;
import java.util.ArrayList;
import java.util.List;
/**
* https://docs.oracle.com/javaee/7/api/
*/
public class Main {
public static void main(String[] args) {
Request request = new Request("request");
Response response = new Response("response");
FilterChain filterChain = new FilterChain();
filterChain.add(new HtmlFilter()).add(new SensitiveFilter());
filterChain.doFilter(request, response);
System.out.println(request.str);
}
}
class Request {
String str;
Request(String str) {
this.str = str;
}
}
class Response {
String str;
Response(String str) {
this.str = str;
}
}
interface Filter {
boolean doFilter(Request request, Response response);
}
/**
* html过滤器
*/
class HtmlFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response) {
request.str += "-->HtmlFilter";
return false;
}
}
/**
* 敏感词过滤器
*/
class SensitiveFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response) {
request.str += "-->SensitiveFilter";
return false;
}
}
class FilterChain implements Filter {
private List<Filter> filters = new ArrayList<>();
public FilterChain add(Filter filter) {
filters.add(filter);
return this;
}
@Override
public boolean doFilter(Request request, Response response) {
for (Filter filter : filters) {
filter.doFilter(request, response);
}
return false;
}
}
版本二:
package com.link.chain.filter.v2;
import java.util.ArrayList;
import java.util.List;
/**
* 用最直观的方式处理response
* 直接将response的处理放在request下面
*/
public class Main {
public static void main(String[] args) {
Request request = new Request("request");
Response response = new Response("response");
FilterChain filterChain = new FilterChain();
filterChain.add(new HtmlFilter()).add(new SensitiveFilter());
filterChain.doFilter(request, response);
System.out.println(request.str);
}
}
class Request {
String str;
Request(String str) {
this.str = str;
}
}
class Response {
String str;
Response(String str) {
this.str = str;
}
}
interface Filter {
boolean doFilter(Request request, Response response);
}
/**
* html过滤器
*/
class HtmlFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response) {
request.str += "-->HtmlFilter";
return false;
}
}
/**
* 敏感词过滤器
*/
class SensitiveFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response) {
request.str += "-->SensitiveFilter";
return false;
}
}
class FilterChain implements Filter {
private List<Filter> filters = new ArrayList<>();
public FilterChain add(Filter filter) {
filters.add(filter);
return this;
}
@Override
public boolean doFilter(Request request, Response response) {
for (Filter filter : filters) {
filter.doFilter(request, response);
}
return false;
}
}
版本三:
package com.link.chain.filter.v3;
import java.util.ArrayList;
import java.util.List;
/**
* 在filterChain中加入位置的记录
* 同时在filter中加入第三个参数
*/
public class Main {
public static void main(String[] args) {
Request request = new Request("request");
Response response = new Response("response");
FilterChain filterChain = new FilterChain();
filterChain.add(new HtmlFilter()).add(new SensitiveFilter());
filterChain.doFilter(request, response, filterChain);
System.out.println(request.str);
System.out.println(response.str);
}
}
class Request {
String str;
Request(String str) {
this.str = str;
}
}
class Response {
String str;
Response(String str) {
this.str = str;
}
}
interface Filter {
boolean doFilter(Request request, Response response, FilterChain filterChain);
}
/**
* html过滤器
*/
class HtmlFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response, FilterChain filterChain) {
request.str += "-->HtmlFilter";
filterChain.doFilter(request, response, filterChain);
response.str += "-->HtmlFilter";
return true;
}
}
/**
* 敏感词过滤器
*/
class SensitiveFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response, FilterChain filterChain) {
request.str += "-->SensitiveFilter";
filterChain.doFilter(request, response, filterChain);
response.str += "-->SensitiveFilter";
return true;
}
}
class FilterChain implements Filter {
private List<Filter> filters = new ArrayList<>();
private int index = 0;
FilterChain add(Filter filter) {
filters.add(filter);
return this;
}
public boolean doFilter(Request request, Response response, FilterChain filterChain) {
if (index == filters.size()) {
return false;
}
Filter filter = filters.get(index);
index++;
return filter.doFilter(request, response, filterChain);
}
}
版本四:
package com.link.chain.filter.v4;
import java.util.ArrayList;
import java.util.List;
/**
* 完全模拟Servlet中的FilterChain
*/
public class Main {
public static void main(String[] args) {
Request request = new Request("request");
Response response = new Response("response");
FilterChain filterChain = new FilterChain();
filterChain.add(new HtmlFilter()).add(new SensitiveFilter());
filterChain.doFilter(request, response);
System.out.println(request.str);
System.out.println(response.str);
}
}
class Request {
String str;
Request(String str) {
this.str = str;
}
}
class Response {
String str;
Response(String str) {
this.str = str;
}
}
interface Filter {
void doFilter(Request request, Response response, FilterChain filterChain);
}
/**
* html过滤器
*/
class HtmlFilter implements Filter {
@Override
public void doFilter(Request request, Response response, FilterChain filterChain) {
request.str += "-->HtmlFilter";
filterChain.doFilter(request, response);
response.str += "-->HtmlFilter";
}
}
/**
* 敏感词过滤器
*/
class SensitiveFilter implements Filter {
@Override
public void doFilter(Request request, Response response, FilterChain filterChain) {
request.str += "-->SensitiveFilter";
filterChain.doFilter(request, response);
response.str += "-->SensitiveFilter";
}
}
class FilterChain {
private List<Filter> filters = new ArrayList<>();
private int index = 0;
FilterChain add(Filter filter) {
filters.add(filter);
return this;
}
public void doFilter(Request request, Response response) {
if (index < filters.size()) {
}
Filter filter = filters.get(index);
index++;
filter.doFilter(request, response, this);
}
}
总结
责任链主要重在责任分离处理,让各个节点各司其职。
责任链上的各个节点都有机会处理事务,但是也可能不会受理请求。
责任链比较长,调试时可能会比较麻烦。
责任链一般用于处理流程节点之类的实际业务场景中。
Spring拦截器链、servlet过滤器链等都采用了责任链设计模式。