描述
- 比如生活中,学生要请假,如果请假三两天,老师即可,如果要请假三两周,就要去找教导主任,如果要请假一年,就要去找校长。这样学生必须记住每个领导的电话联系方式等。难度增加。
- 为了避免请求者(学生)与多个处理者(领导们)耦合,将所有处理者通过前一个对象记住下一个对象的引用,连成一条线(责任链模式)。
角色
- 抽象处理者角色:处理规范,且定义了后续连接。
- 具体处理者角色:实现抽象处理者,判断本次请求是否处理,是否要交给后续连接
- 客户角色:创建处理者,并向处理者提交请求。不关心具体处理细节。
实现
public class Test {
public static void main(String[] args) {
StudentRequest studentRequest = new StudentRequest("小明", 60, "参加奥运会");
TeacherHandler teacherHandler = new TeacherHandler();
DirectorHandler directorHandler = new DirectorHandler();
PrincipalHandler principalHandler = new PrincipalHandler();
teacherHandler.setNextHandler(directorHandler);
directorHandler.setNextHandler(principalHandler);
teacherHandler.submit(studentRequest);
}
}
class StudentRequest {
private String name;
private Integer number;
private String content;
public String getName() {
return name;
}
public Integer getNumber() {
return number;
}
public String getContent() {
return content;
}
StudentRequest(String name, Integer number, String content) {
this.name = name;
this.number = number;
this.content = content;
}
}
abstract class Handler {
public static final Integer GRADE_ONE = 7;
public static final Integer GRADE_TWO = 30;
public static final Integer GRADE_THREE = 365;
private Integer numberStart;
private Integer numberEnd;
private Handler nextHandler;
Handler(Integer number) {
this.numberStart = number;
}
Handler(Integer numberStart, Integer numberEnd) {
this.numberStart = numberStart;
this.numberEnd = numberEnd;
}
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void dealWith(StudentRequest request);
public final void submit(StudentRequest request) {
if (request.getNumber() >= this.numberStart && request.getNumber() <= this.numberEnd) {
this.dealWith(request);
}else if (this.nextHandler != null && request.getNumber() > this.numberEnd) {
this.nextHandler.submit(request);
} else {
System.out.println("审批失败,流程结束");
}
}
}
class TeacherHandler extends Handler{
TeacherHandler() {
super(0, GRADE_ONE);
}
@Override
public void dealWith(StudentRequest request) {
System.out.println(String.format("请假人:%s,请假天数:%d,请假原因:%s", request.getName(), request.getNumber(), request.getContent()));
System.out.println("老师审批通过");
}
}
class DirectorHandler extends Handler{
DirectorHandler() {
super(0, GRADE_TWO);
}
@Override
public void dealWith(StudentRequest request) {
System.out.println(String.format("请假人:%s,请假天数:%d,请假原因:%s", request.getName(), request.getNumber(), request.getContent()));
System.out.println("主管审批通过");
}
}
class PrincipalHandler extends Handler{
PrincipalHandler() {
super(0, GRADE_THREE);
}
@Override
public void dealWith(StudentRequest request) {
System.out.println(String.format("请假人:%s,请假天数:%d,请假原因:%s", request.getName(), request.getNumber(), request.getContent()));
System.out.println("校长审批通过");
}
}
优点
- 降低请求发送者和处理者之间耦合度。
- 高扩展,可以插拔式的添加或修改或删除某个处理节点,不影响其它节点,满足开闭原则。
- 一个类只需要维护下一个节点的引用,减少if else if判断。
- 明确各个节点的职责,符合单一职责原则。
缺点
- 无法保证每个请求一定被处理,可能到责任链的末尾都无法处理(比如例子中的请假2年)。
- 责任链过长,系统性能有一定的影响。
- 责任链建立的合理性,需要由客户端来保证,增加了客户端的复杂度,设置错误可能会导致死循环。
JAVA中的例子
- Servlet中的Filter链。执行chain.doFilter()才能到下一个请求。
public class TenantFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("前处理");
chain.doFilter(httpServletRequest, response);
System.out.println("后处理");
}
}