前言

责任链模式是一种链式结构,就是由一个个节点首尾相接串起来的结构,具有很好的灵活性,将每一个节点看作是一个对象,每一个对象拥有不同的处理逻辑,将一个请求从链式的首端发出,沿着链的路径依此传递每一个节点对象,直到有对象处理这个请求为止,我们将这样一种模式称为责任链模式。

定义

使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

使用场景

  • 1、多个对象可以处理同一请求,但具体哪个对象处理则是在运行时动态决定
  • 2、在请求者不明确的情况下向多个对象中的一个提交一个请求
  • 3、需要动态指定一组对象的处理请求

类图

角色介绍:

  • AbstractHandler - 抽象处理者角色,声明一个请求处理的方法(handle())、一个获得处理级别的方法(getHandlerLever())和封装了一个对具体的处理转发逻辑实现的方法(handleRequest()),并在其中保持对下一个处理节点的AbstractHandler对象的引用(nextHandler)
  • ConcreteHandler1、2 - 具体处理者角色,对请求进行处理,如果不能处理就将请求转发给下一个节点上的处理对象
  • AbstractRequest - 抽象的请求类,里面声明了一个获得请求内容的方法(getContent())和一个获得请求处理级别的方法(getRequestLever())
  • ConcreteRequest - 具体的请求类

简单实现

在一个公司中,员工拿到了一份合同,需要上级的签名,于是员工就把合同给组长,但是组长没有权限签名,于是组长就把合同给经理,但是经理也没有足够的权限签名,于是经理就把合同给老板,老板二话不说就把合同给签了。上面的例子就是责任链模式,员工是请求的发起者,处于链的底端,而老板是处于链条顶端的类,员工发起请求后,请求经过层层转发,直至请求被处理,员工只是和组长发生了关联,后面合同被谁处理,员工并不知道,也并不关心,他在乎的是合同签名的结果,责任链模式很好的将请求的发起者与处理者解耦,下面用代码来模拟。

抽象的员工,即AbstractHandler角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class Staff {

protected Staff nextHandler;//上一级领导处理者

//处理转发的逻辑
public final void handleRequest(Contract contract){
if(contract.getContractLever() < getHandlerLever()){
handle(contract);
}else {
if(nextHandler != null){
nextHandler.handleRequest(contract);
}
}
}

public abstract int getHandlerLever();//自身能处理请求的级别
public abstract void handle(Contract contract);//具体的处理过程
}

在这个抽象的处理者中,一是定义了两个接口来确定一个Staff应有的行为和属性,二是封装了一个处理请求的逻辑转发方法,确定当前Staff是否有足够的级别来处理当前合同,如果没有,就把合同转发给上一级Staff,接下来是各个实现类。

组长,即ConcreteHandler角色

1
2
3
4
5
6
7
8
9
10
11
12
13
public class CroupStaff extends Staff {

@Override
public int getHandlerLever() {
return 1;
}

@Override
public void handle(Contract contract) {
System.out.println("组长签名了合同!");
}

}

经理,即ConcreteHandler角色

1
2
3
4
5
6
7
8
9
10
11
public class ManagerStaff extends Staff {
@Override
public int getHandlerLever() {
return 2;
}

@Override
public void handle(Contract contract) {
System.out.println("经理签名了合同!");
}
}

老板,即ConcreteHandler角色

1
2
3
4
5
6
7
8
9
10
11
public class BossStaff extends Staff {
@Override
public int getHandlerLever() {
return 3;
}

@Override
public void handle(Contract contract) {
System.out.println("老板签名了合同!");
}
}

接下来看一看请求,就是合同。

抽象的合同类,即AbstractRequest角色

1
2
3
4
public abstract class Contract {
public abstract String getContext();//获得合同具体内容
public abstract int getContractLever();//获得合同处理级别
}

最后员工从组长发起请求。

请求发起者,员工

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Employee {

public static void main(String[] args){
//构造各个节点对象
GroupStaff groupStaff = new GroupStaff();
ManagerStaff managerStaff = new ManagerStaff();
BossStaff bossStaff = new BossStaff();
//构成一条链
groupStaff.nextHandler = managerStaff;
managerStaff.nextHandler = bossStaff;
//发起请求
Contract contract = new ConcreteContract();
groupStaff.handleRequest(contract);
}

}

输出结果:
老板签名了合同!

其实这里也可以直接绕过组长和经理,直接找老板签名,这也是责任链模式的灵活性,请求的发起可以从任意节点发起,同时也可以改变责任链模式内部的传递规则,如直接找老板签名。

总结

对于责任链模式中的节点,有两个行为,一是处理请求,二是将请求转发给下一个节点,不允许某个节点处理者处理了请求后又把节点转发给下一个节点。对于责任链中的请求,只有俩个结果,一个是被某个节点处理,一个是所有对象均没有处理。

本文相关源码位置