责任链模式(Chain of Responsibility)
定义
责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。——阎宏博士的《Java与模式》
责任链模式的结构
角色
1、抽象处理者角色(Handler):定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
2、具体处理者角色(ConcreteHandler):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
UML图
代码
public abstract class Handler {
protected Handler next;//持有后续的责任对象
/**
* 处理请求方法
* @return
*/
public abstract void handlerRequest();
public Handler getNext() {
return next;
}
public void setNext(Handler next) {
this.next = next;
}
}
public class HandlerA extends Handler {
/**
* 处理请求方法的具体实现(这是纯责任链的实现)
*/
public void handlerRequest(){
Handler next = this.getNext();
if(next==null){
System.out.println("A处理请求");
}else {
next.handlerRequest();
}
}
}
public class HandlerB extends Handler {
/**
* 处理请求方法的具体实现(这是纯责任链的实现)
*/
public void handlerRequest(){
Handler next = this.getNext();
if(next==null){
System.out.println("B处理请求");
}else {
next.handlerRequest();
}
}
}
public class Client {
public static void main(String[] args) {
//组装责任链
Handler handlerA = new HandlerA();
Handler handlerB = new HandlerB();
handlerA.setNext(handlerB);
//提交请求
handlerA.handleRequest();
}
}
使用场景
考虑这样一个场景:团建费用的审批流程。
不同级别的领导能够审批的最大金额各不相同,比如:项目经理只能审批500元以内;部门经理能审批1000元一捏的申请;总经理可以审批任意额度的申请。
当某人提出团建费用申请请求之后,该请求会经由项目经理、部门经理、总经理的审批,但是申请者是不知道最终是由谁审批的,每个领导会根据自己的责任范围,来判断是处理请求还是交给更高级别的领导处理,只要有领导处理了,流程就终止。
需要将每个领导的处理单独出来,实现成单独的职责处理对象,然后为他们提供一个公共的、抽象的肤质则对象,按照先后链路进行排列,或者按照客户端的需求动态的组合责任链,以实现功能。
UML图如下:
团建费审批UML图.png
纯的和不纯的责任链
一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一是承担责任,而是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又 把责任向下传的情况。
在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接收;在一个不纯的责任链模式里面,一个请求可以最终不被任何接收端对象所接收。
纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。有些人认为不纯的责任链根本不是责任链模式,这也许是有道理的。但是在实际的系统里,纯的责任链很难找到。如果坚持责任链不纯便不是责任链模式,那么责任链模式便不会有太大意义了。
注:tomcat中的Filter就是使用了不纯的责任链。