职责链模式
定义
使多个对象都可以处理一个请求,将这个对象连成一条链,并沿着这条链传递该请求,直到其中某个对象可以处理它为止。
结构
抽象处理类:它持有自身的一个引用,定义了一个用来处理请求的接口
具体处理类:实现了抽象处理类的接口方法,在方法内部判断是否让其处理请求还是放到下一个处理类来处理。
类图
个人理解:职责链模式的思想是复合+转发的方式实现的,只不过这次复合的对象是它本身,通过持有自身的引用可以使得处理类形成一个链,在处理方法内部判断是否让下一个处理类类处理还是自身来处理。
意图:
抽象处理类:
public abstract class Handler {
public Handler chain;
public void setChain(Handler chain) {
this.chain = chain;
}
public abstract void handleRequest(int request);
}
具体处理类:
public class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(int request) {
if(request > 0 && request <= 10){
System.out.println("执行A处理方法");
} else if (chain != null) {
chain.handleRequest(request);
}
}
}
public class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(int request) {
if(request > 10 && request <= 20){
System.out.println("执行B处理方法");
} else if (chain != null) {
chain.handleRequest(request);
}
}
}
public class ConcreteHandlerC extends Handler {
@Override
public void handleRequest(int request) {
if(request > 20){
System.out.println("执行C处理方法");
}
}
}
测试类:
public static void main(String[] args) {
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();
handlerA.setChain(handlerB);
handlerB.setChain(handlerC);
handlerA.handleRequest(5);
handlerA.handleRequest(11);
handlerA.handleRequest(30);
}
测试结果:
案例
我们以员工申请请假需要经过领导审批为例。组长、总监、经理作为处理审批申请的具体处理类,它们各自持有自身的引用,通过请求中请假天数判断由谁来处理审批流程。
抽象处理类:
public abstract class AbstractHandler {
public AbstractHandler chain;
public void setChain(AbstractHandler chain) {
this.chain = chain;
}
public abstract void handleRequest(int request);
}
组长处理类:
public class TeamLeaderHandler extends AbstractHandler {
@Override
public void handleRequest(int request) {
if(request>0&&request<=2){
System.out.println("组长同意请假"+request+"天");
}else if(chain!=null){
chain.handleRequest(request);
}
}
}
总监处理类:
public class DirectorHandler extends AbstractHandler {
@Override
public void handleRequest(int request) {
if(request>2&&request<=5){
System.out.println("总监同意请假"+request+"天");
}else if(chain!=null){
chain.handleRequest(request);
}
}
}
经理处理类:
public class ManagerHandler extends AbstractHandler{
@Override
public void handleRequest(int request) {
if(request>5){
System.out.println("经理同意请假"+request+"天");
}
}
}
测试类:
public static void main(String[] args) {
AbstractHandler teamLeader = new TeamLeaderHandler();
AbstractHandler director = new DirectorHandler();
AbstractHandler manager = new ManagerHandler();
teamLeader.setChain(director);
director.setChain(manager);
teamLeader.handleRequest(1);
teamLeader.handleRequest(3);
teamLeader.handleRequest(15);
}
测试结果:
优点
1.新增具体处理类方便灵活。
2.将请求的发送者(即客户端)和请求的接受者(处理类)解耦合。
缺点
可能出现请求无法被处理的情况。
JDK类库中的职责链模式
java.util.loggingLogger#log(LogRecord ld)(暂时还不明白这个为什么会使职责链模式!)
javax.servlet.Filter#doFilter(req,rep)
典型的例子是struts2的核心过滤器:StrutsPrepareAndExecuteFilter
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
prepare.setEncodingAndLocale(request, response);
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
chain.doFilter(request, response);
} else {
request = prepare.wrapRequest(request);
ActionMapping mapping = prepare.findActionMapping(request, response, true);
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
execute.executeAction(request, response, mapping);
}
}
} finally {
prepare.cleanupRequest(request);
}
}