责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推,发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求。例如:公司员工请假,可批假的领导有部门负责人、副总经理、总经理等,但每个领导能批准的天数不同,员工必须根据自己要请假的天数去找不同的领导签名,也就是说员工必须记住每个领导的姓名、电话和地址等信息,这增加了难度。这样的例子还有很多,如生活中的“击鼓传花”游戏,计算机的异常处理中,处理程序根据异常的类型决定自己是否处理该异常;还有 Struts2 的拦截器、JSP 和 Servlet 的 Filter 等,所有这些,如果用责任链模式都能很好解决。
意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
何时使用:在处理消息的时候以过滤很多道。
如何解决:拦截的类都实现统一接口。
关键代码:Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。
优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。
缺点: 1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。
使用场景: 1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 3、可动态指定一组对象处理请求。
注意事项:在 JAVA WEB 中遇到很多应用。
职责链模式主要包含以下角色:
1.抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
2.具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
3.客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
其结构图如图所示:


如职员申请经费,不同的金额由不同的上级批准
实现:
/**
*
* @ClassName: Job
* @Description: 抽象处理者:职位
* @author: ljx
* @date: 2019年3月4日 下午3:34:33
*/
public abstract class Job {
//聚合自己
private Job next;
//获取下一个对象
public Job getNext() {
return next;
}
//设置下一个对象
public void setNext(Job next) {
this.next = next;
}
//处理请求
public abstract void handleRequest(int money);
}
/**
*
* @ClassName: ProjectManager
* @Description: 具体处理者1:项目经理
* @author: ljx
* @date: 2019年3月4日 下午3:59:21
*/
public class ProjectManager extends Job{
@Override
public void handleRequest(int money) {
if(money < 500){
System.out.println("额度小于500,批准");
}else{
if(getNext() != null){
//如果有下一个处理者,则把请求发送个下一个处理者
getNext().handleRequest(money);
}else{
System.out.println("额度太大,无人处理");
}
}
}
}
/**
*
* @ClassName: DepartmentManager
* @Description: 具体实现者2:部门经理
* @author: ljx
* @date: 2019年3月4日 下午4:09:05
*/
public class DepartmentManager extends Job {
@Override
public void handleRequest(int money) {
if(money < 1000){
System.out.println("额度小于1000,批准");
}else{
if(getNext() != null){
//如果有下一个处理者,则把请求发送个下一个处理者
getNext().handleRequest(money);
}else{
System.out.println("额度太大,无人处理");
}
}
}
}
/**
*
* @ClassName: GeneralManager
* @Description: 具体实现者3:总经理
* @author: ljx
* @date: 2019年3月4日 下午4:11:40
*/
public class GeneralManager extends Job {
@Override
public void handleRequest(int money) {
if(money < 1000){
System.out.println("额度小于2000,批准");
}else{
if(getNext() != null){
//如果有下一个处理者,则把请求发送个下一个处理者
getNext().handleRequest(money);
}else{
System.out.println("额度太大,无人处理");
}
}
}
}
/**
*
* @ClassName: ClientTest
* @Description: 请求客户端
* @author: ljx
* @date: 2019年3月4日 下午4:13:39
*/
public class ClientTest {
public static void main(String[] args) {
Job project = new ProjectManager();
Job department = new DepartmentManager();
Job general = new GeneralManager();
project.setNext(department);
department.setNext(general);
project.handleRequest(100);
}
}
职责链模式存在以下两种情况:
1.纯的职责链模式:一个请求必须被某一个处理者对象所接收,且一个具体处理者对某个请求的处理只能采用以下两种行为之一:自己处理(承担责任);把责任推给下家处理。
2.不纯的职责链模式:允许出现某一个具体处理者对象在承担了请求的一部分责任后又将剩余的责任传给下家的情况,且个请求可以最终不被任何接收端对象所接收。
在实际的系统里,纯的责任链很难找到。如果坚持责任链不纯便不是责任链模式,那么责任链模式便不会有太大意义了。
... ..., 欢迎指正!