共计 3685 个字符,预计需要花费 10 分钟才能阅读完成。
0x01:责任链模式简介
在责任链模式中,很多对象由每一个对象对其下家的援用而连接起来造成一条链。申请在这个链上进行传递,直到链上的某一个对象决定解决此申请。收回这个申请的客户端并不知道链上的哪一个对象最终解决这个申请,这使得零碎能够在不影响客户端的状况下动静地从新组织和调配责任。责任链模式的 UML 类图如下:
其中,Handler 是形象解决者,定义了一个解决申请的接口;ConcreteHandler 是具体解决者,解决它所负责的申请,可拜访它的后继者,如果可解决该申请就解决,否则就将该申请转发给它的后继者。次要角色如下:
形象解决者 (Handler):定义出一个解决申请的接口。如果须要接口能够定义出一个办法以设定和返回对下一个解决对象的援用。这个角色通常由一个抽象类或者接口实现。Handler 类的聚合关系给出了具体子类对下一个解决对象的援用,形象办法 handleRequest() 标准了子类解决申请的操作。
具体解决者(ConcreteHandler):具体解决者接到申请后,能够抉择将申请解决掉,或者将申请传给下一个 Handler 解决。因为具体解决者持有对一个解决对象的援用,因而,如果须要具体解决者能够拜访下一个解决对象。
0x02:责任链模式实现
在工作中,免不了须要进行报销。当初与报销这个业务流程来实现责任链模式。约定如下:
报销金额 0 ~ 1W 直属下属审批即可,报销级别为 1;
报销金额 1W+ ~ 5W 部门经理审批即可,报销级别为 2;
报销金额 5W+ 公司负责人审批,报销级别为 3;
Request 类负责封装申请,具体内容需依据业务产生
public class Request {
private int level;
public Request(int level) {this.level = level;}
public void setLevel(int level) {this.level = level;}
public int getLevel() {return this.level;}
}
Response 类负责封装链中返回的后果,具体内容需依据业务产生
// 解决者返回的数据
public class Response {
private int result;
public Response(int result) {this.result = result;}
public int getResult() {return result;}
public void setResult(int result) {this.result = result;}
}
形象解决者(Handler)
public abstract class Handler {
// 下一个解决者
private Handler nextHandler;
public final Response handlerMessage(Request request) {
Response response = null;
if(this.getLevel() == request.getLevel()) { // 判断是否是本人的解决级别
response = this.process(request);
} else {if(this.nextHandler != null) { // 下一解决者不为空
response = this.nextHandler.handlerMessage(request);
} else {// 没有适当的解决者,业务自行处理}
}
return response;
}
// 设定下一个解决者
public void setNext(Handler handler) {this.nextHandler = handler;}
// 每个解决者能够解决的报销等级
protected abstract int getLevel();
// 每个解决者都必须实现的解决工作
protected abstract Response process(Request request);
}
具体解决者(ConcreteHandler)
直属下属
/**
* 直属下属
*
*/
public class DirectorManager extends Handler {
@Override
protected int getLevel() {return 1;}
@Override
protected Response process(Request request) {System.out.println("DirectorManager process>>");
return new Response(1);
}
}
部门长
/**
* 直属下属
*
*/
public class DeptManager extends Handler {
@Override
protected int getLevel() {return 2;}
@Override
protected Response process(Request request) {System.out.println("DeptManager process>>");
return new Response(2);
}
}
公司负责人
/**
* 直属下属
*
*/
public class CompanyManager extends Handler {
@Override
protected int getLevel() {return 3;}
@Override
protected Response process(Request request) {System.out.println("CompanyManager process>>");
return new Response(3);
}
}
责任链模式测试代码
public class Client {public static void main(String[] args) {Handler handler1 = new DirectorManager();
Handler handler2 = new DeptManager();
Handler handler3 = new CompanyManager();
// 设置链中的阶段程序 1->2->3
handler1.setNext(handler2);
handler2.setNext(handler3);
// 提交申请返回后果
Response response = handler1.handlerMessage(new Request(2));
}
}
0x03:责任链模式在框架的使用
责任链模式的使用可是说十分宽泛,上面来理解一下都有哪些框架应用了该设计模式
J2EE
在 Servlet 技术中,别离定义了一个 Filter 和 FilterChain 接口
Filter 接口
public interface Filter {default public void init(FilterConfig filterConfig) throws ServletException {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException;
default public void destroy() {}
}
FilterChain 接口
public interface FilterChain {public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException;
}
外围解决类 ApplicationFilterChain
public final class ApplicationFilterChain implements FilterChain {
@Override
public void doFilter(ServletRequest request, ServletResponse response)
// 省略
}
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {// 省略}
// 省略
}
在应用 Filter 时,如果须要交给下一个 Filter 解决,都会调用如下一段代码:
chain.doFilter(request, response);
SpringMVC
如果有看过 SpringMVC 的 DispatcherServlet 类的源码,能够看到如下一段代码
HandlerExecutionChain 类是一个责任链,其中的办法 applyPreHandler(),applyPostHandle() 和 triggerAfterCompletion() 相当于具体的解决类;在 DispatcherServlet 类的 doDispatch() 办法中进行条件判断实现解决的传递。如果想深刻理解 HandlerExecutionChain 类的调用关系,能够跟踪一下 DispatcherServlet 类的 doDispatch() 办法。