在现实生活中,常常会出现这样的事例:一个请求有多个对象可以处理,但每个对象的处理条件或权限不同。例如,公司员工请假,可批假的领导有部门负责人、副总经理、总经理等,但每个领导能批准的天数不同,员工必须根据自己要请假的天数去找不同的领导签名,也就是说员工必须记住每个领导的姓名、电话和地址等信息,这增加了难度。这样的例子还有很多,如找领导出差报销、生活中的“击鼓传花”游戏等
在计算机软硬件中也有相关例子,如异常处理中,处理程序根据异常的类型决定自己是否处理该异常;还有 Struts2 的拦截器、JSP 和 Servlet 的 Filter 等,所有这些,如果用责任链模式都能很好解决。
基本介绍 定义为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,所提交的请求沿着链传递链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给链上的下一一个对象。
使用场景举例 公司里面,报销个单据需要经过流程:抽象处理者角色
abstract class Handler
{
private Handler next;
public void setNext(Handler next)
{
this.next=next;
}
public Handler getNext()
{
return next;
}
//处理请求的方法
public abstract void handleRequest(String request);
}
具体处理者角色1
class ConcreteHandler1 extends Handler
{
public void handleRequest(String request)
{
if(request.equals("one"))
{
System.out.println("具体处理者1负责处理该请求!");
}
else
{
if(getNext()!=null)
{
getNext().handleRequest(request);
}
else
{
System.out.println("没有人处理该请求!");
}
}
}
}
具体处理者角色2
class ConcreteHandler2 extends Handler
{
public void handleRequest(String request)
{
if(request.equals("two"))
{
System.out.println("具体处理者2负责处理该请求!");
}
else
{
if(getNext()!=null)
{
getNext().handleRequest(request);
}
else
{
System.out.println("没有人处理该请求!");
}
}
}
}
客户端调用
public class ChainOfResponsibilityPattern
{
public static void main(String[] args)
{
//组装责任链
Handler handler1=new ConcreteHandler1();
Handler handler2=new ConcreteHandler2();
handler1.setNext(handler2);
//提交请求
handler1.handleRequest("two");
}
}
结果
具体处理者2负责处理该请求!
实例分析
实例一——学校采购审批
采购员采购教学器材
如果金额 小于等于 5000, 由教学主任审批 (0<=x<=5000) 如果金额 小于等于 10000, 由院长审批 (5000<x<=10000) 如果金额 小于等于 30000, 由副校长审批 (10000<x30000) 传统方式实现
接收到一个采购请求后,根据采购金额来调用对应的 Approver (审批人)完成审批。
客户端这里会使用到 分支判断(比如 switch) 来对不同的采购请求处理, 这样就存在如下问题:
如果各个级别的人员审批金额发生变化,在客户端的也需要变化 客户端必须明确的知道 有多少个审批级别和访问这样 对一个采购请求进行处理 和 Approver (审批人) 就存在强耦合关系,不利于代码的扩展和维护
责任链模式实现 UML类图 代码实现抽象审批人
public abstract class Approver {
//下一个处理者(聚合)
Approver approver;
// 名字
String name;
public Approver(String name) {
this.name = name;
}
//下一个处理者
public void setApprover(Approver approver) {
this.approver = approver;
}
//处理审批请求的方法,得到一个请求, 处理是子类完成,因此该方法做成抽象
public abstract void processRequest(PurchaseRequest purchaseRequest);
}
系主任审批
public class DepartmentApprover extends Approver {
public DepartmentApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if(purchaseRequest.getPrice() <= 5000) {
System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");
}else {
approver.processRequest(purchaseRequest);
}
}
}
学院审批
public class CollegeApprover extends Approver {
public CollegeApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if(purchaseRequest.getPrice() < 5000 && purchaseRequest.getPrice() <= 10000) {
System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");
}else {
approver.processRequest(purchaseRequest);
}
}
}
副校长审批
public class ViceSchoolMasterApprover extends Approver {
public ViceSchoolMasterApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if(purchaseRequest.getPrice() < 10000 && purchaseRequest.getPrice() <= 30000) {
System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");
}else {
approver.processRequest(purchaseRequest);
}
}
}
校长审批
public class SchoolMasterApprover extends Approver {
public SchoolMasterApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if(purchaseRequest.getPrice() > 30000) {
System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");
}else {
approver.processRequest(purchaseRequest);
}
}
}
请求类
public class PurchaseRequest {
//请求类型
private int type = 0;
//请求金额
private float price = 0.0f;
private int id = 0;
//构造器
public PurchaseRequest(int type, float price, int id) {
this.type = type;
this.price = price;
this.id = id;
}
public int getType() {
return type;
}
public float getPrice() {
return price;
}
public int getId() {
return id;
}
}
客户端调用
public class Client {
public static void main(String[] args) {
//创建一个请求
PurchaseRequest purchaseRequest = new PurchaseRequest(1, 31000, 1);
//创建相关的审批人
DepartmentApprover departmentApprover = new DepartmentApprover("张主任");
CollegeApprover collegeApprover = new CollegeApprover("李院长");
ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover("王副校");
SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("佟校长");
//需要将各个审批级别的下一个设置好 (处理人构成环形: )
departmentApprover.setApprover(collegeApprover);
collegeApprover.setApprover(viceSchoolMasterApprover);
viceSchoolMasterApprover.setApprover(schoolMasterApprover);
schoolMasterApprover.setApprover(departmentApprover);
departmentApprover.processRequest(purchaseRequest);
viceSchoolMasterApprover.processRequest(purchaseRequest);
}
}
结果
请求编号 id= 1 被 佟校长 处理
请求编号 id= 1 被 佟校长 处理
注意
将具体的处理者的链状关系设置成环形的好处:无论从哪一个处理者开始调用,都不会出现空指针没有下一个处理者的错误。
责任链模式通常在以下几种情况使用。
有多个对象可以处理一个请求,哪个对象处理该请求由运行时刻自动确定。 可动态指定一组对象处理请求,或添加新的处理者。 在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。 模式扩展职责链模式存在以下两种情况。
纯的职责链模式:一个请求必须被某一个处理者对象所接收,且一个具体处理者对某个请求的处理只能采用以下两种行为之一:自己处理(承担责任);把责任推给下家处理。 不纯的职责链模式:允许出现某一个具体处理者对象在承担了请求的一部分责任后又将剩余的责任传给下家的情况,且一个请求可以最终不被任何接收端对象所接收。