通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
该模式在生活中很常见,比如:汽车制造、物流分拣、食品加工、质量检测等等,生活中更多的是这样的非纯责任模式,也就是说,每个节点都会根据自己的职责操作自己对应的部分,然后转交下一节点处理;也有纯责任模式,比如质检,一旦某个节点出问题直接不合格并打回。这种模式一般是从低等级往高等级层层请求。
我们来举个团建经费申请的例子:
场景设定:
项目经理(500) - 部门主管(1000) - 总经理(2000) - 老板(2000~5000)
首先抽象出经理,并创建链的连接关系
package com.zndroid.dm.ChainOfResponseModel;
/**
* Created by luzhenyu on 2017/9/18.
*/
/**抽象出可处理的对象,并提供‘链’的关联和具体类的处理请求*/
public abstract class Manager {
public abstract void request(int mount);//请求入口
public void setNextManager(Manager nextManager) {
this.nextManager = nextManager;
}
protected Manager nextManager;//提供链关联
public void done() {
System.out.println("[OK...]");
}
}
具体节点
package com.zndroid.dm.ChainOfResponseModel.impl;
import com.zndroid.dm.ChainOfResponseModel.Manager;
/**
* Created by luzhenyu on 2017/9/18.
*/
public class ProjectManager extends Manager {
@Override
public void request(int mount) {
if (mount <= 500) {
System.out.println("项目经理审批通过,申请金额:" + mount);
done();
return;
}
else {
System.out.println("金额超出项目经理的范围,开始转交上级处理...");
nextManager.request(mount);
}
}
}
package com.zndroid.dm.ChainOfResponseModel.impl;
import com.zndroid.dm.ChainOfResponseModel.Manager;
/**
* Created by luzhenyu on 2017/9/18.
*/
public class DepartmentManager extends Manager {
@Override
public void request(int mount) {
if (mount > 500 && mount <= 1000) {
System.out.println("部门主管审批通过,申请金额:" + mount);
done();
return;
}
else {
System.out.println("金额超出部门主管的范围,开始转交上级处理...");
nextManager.request(mount);
}
}
}
package com.zndroid.dm.ChainOfResponseModel.impl;
import com.zndroid.dm.ChainOfResponseModel.Manager;
/**
* Created by luzhenyu on 2017/9/18.
*/
public class GeneralManager extends Manager {
@Override
public void request(int mount) {
if (mount > 1000 && mount <= 2000) {
System.out.println("总经理审批通过,申请金额:" + mount);
done();
return;
}
else {
System.out.println("金额超出总经理的范围,开始转交上级处理...");
nextManager.request(mount);
}
}
}
package com.zndroid.dm.ChainOfResponseModel.impl;
import com.zndroid.dm.ChainOfResponseModel.Manager;
/**
* Created by luzhenyu on 2017/9/18.
*/
public class BossManager extends Manager {
@Override
public void request(int mount) {
if (mount > 2000 && mount <= 5000) {
System.out.println("老板审批通过,申请金额:" + mount);
done();
return;
}
else {
System.out.println("老板哭穷中...");
}
}
}
使用如下
/**
* 职责链模式
* 使多个对象都有可能处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
*
* 往往它是一个从最低级到上层的请求方式,职责链模式可以灵活的改变内部的传递规则,每个人可以动态的制定自己的继承者。
* 如果初始层级暂时不在或消失,请求也可以直接发送给其他层级,后续职责链还会继续进行。而且可以随时增加和修改处理一个请求的结构,增加了给对象指派的职责的灵活性。
*
* 优点:
* 调用者不需知道具体谁来处理请求,也不知道链的具体结构,降低了节点域节点的耦合度;可在运行时动态修改链中的对象职责,增强了给对象指派职责的灵活性;
* 缺点:
* 没有明确的接收者,可能传到链的最后,也没得到正确的处理;系统性能会受到影响;代码调试比较繁琐。
*
* 具体应用:
* OA系统;在java中的实际应用有Servlet中的过滤器(Filter);Struts2的拦截器(Interceptor),生活中大部分流程还是不纯的责任链,也就是每个节点的对象都有可能
* 做了对应的操作,高层次的操作要以低层次的为依据,比如:公司请假肯定要部门经理先同意才能走到下一级,而不是说,部门经理不同意就会走到老板那。
* */
//下面来模拟一下公司的团建申请
//比方说现在有三个老总可以处理团建申请,他们的可以批示的金额分变为:
//项目经理(500) - 部门主管(1000) - 总经理(2000) - 老板(2000~5000)
//创建节点:
ProjectManager projectManager = new ProjectManager();
DepartmentManager departmentManager = new DepartmentManager();
com.zndroid.dm.ChainOfResponseModel.impl.GeneralManager generalManager= new com.zndroid.dm.ChainOfResponseModel.impl.GeneralManager();
BossManager bossManager = new BossManager();
//建立链接:
projectManager.setNextManager(departmentManager);
departmentManager.setNextManager(generalManager);
generalManager.setNextManager(bossManager);
projectManager.request(3000);
log("----------------我是分割线-----------------");
运行结果:
[ ======================================== ]
金额超出项目经理的范围,开始转交上级处理...
金额超出部门主管的范围,开始转交上级处理...
金额超出总经理的范围,开始转交上级处理...
老板审批通过,申请金额:3000
[OK...]
[ ----------------我是分割线----------------- ]
[ ======================================== ]