一、概述
责任链模式(Chain of Responsibility Pattern)使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
责任链模式很好理解, 比如平时在公司请假,请假小于3天,小组长审批即可;3天到5天,需要小组长和部门领导审批二级审批;大于5天的,需要小组长、部门领导和VP审批三级审批。
责任链模式的2种角色:
抽象处理角色(Handler):定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
具体处理者角色(ConcreteHandler):实现抽象处理者的处理方法,该处理方法中会进行判断能够处理本次请求,如果可以则将请求转给其后继者继续执行处理方法。
二、优缺点
优点:
1、降低耦合度。它将请求的发送者和接收者解耦。
2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
4、增加新的请求处理类很方便。
缺点:
1、不能保证请求一定被接收。
2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
3、可能不容易观察运行时的特征,有碍于除错。
三、实现方式
以上面请假为案例简单实现责任链模式。
抽象处理类
public abstract class Handler {
//天数阈值
protected int daysThreshold;
private Handler nextHandler;
public void setNextHandler(Handler nextHandler){
this.nextHandler = nextHandler;
}
public void leaveHandler(int days, String msg,int step){
if(days >= this.daysThreshold){
pass(msg, step++);
}
if(nextHandler != null){
nextHandler.leaveHandler(days,msg, step);
}
}
abstract void pass(String msg, int step);
}
具体处理类(组长审批)
public class GroupLeaderHandler extends Handler{
public GroupLeaderHandler(int daysThreshold){
this.daysThreshold = daysThreshold;
}
@Override
void pass(String msg, int step) {
System.out.println("("+step+")组长审批:" + msg);
}
}
具体处理类(部门领导审批)
public class DeptLeaderHandler extends Handler{
public DeptLeaderHandler(int daysThreshold){
this.daysThreshold = daysThreshold;
}
@Override
void pass(String msg, int step) {
System.out.println("("+step+")部门领导审批:" + msg);
}
}
具体处理类(VP审批)
public class VPHandler extends Handler{
public VPHandler(int daysThreshold){
this.daysThreshold = daysThreshold;
}
@Override
void pass(String msg, int step) {
System.out.println("("+step+")大大领导VP审批:" + msg);
}
}
客户端
public class Client {
public static Handler getClient(){
/**
* 1、小于3天,需要组长审批
* 2、3-5天,需要组长、部门领导审批
* 3、大于5天,需要组长、部门领导、VP审批
*/
Handler groupLeader = new GroupLeaderHandler(1);//组长审批
Handler departmentLeader = new DeptLeaderHandler(3);//部门领导审批
Handler boss = new VPHandler(6);//Vp审批
groupLeader.setNextHandler(departmentLeader);
departmentLeader.setNextHandler(boss);
return groupLeader;
}
public static void main(String[] args) {
Handler client = getClient();
for(int i=1;i<=10;i++){
client.leaveHandler(i,"请"+i+"天假",1);
System.out.println("----------------");
}
}
}
结果输出
(1)组长审批:请1天假
----------------
(1)组长审批:请2天假
----------------
(1)组长审批:请3天假
(2)部门领导审批:请3天假
----------------
(1)组长审批:请4天假
(2)部门领导审批:请4天假
----------------
(1)组长审批:请5天假
(2)部门领导审批:请5天假
----------------
(1)组长审批:请6天假
(2)部门领导审批:请6天假
(3)大大领导VP审批:请6天假
----------------
(1)组长审批:请7天假
(2)部门领导审批:请7天假
(3)大大领导VP审批:请7天假
----------------
(1)组长审批:请8天假
(2)部门领导审批:请8天假
(3)大大领导VP审批:请8天假
----------------
(1)组长审批:请9天假
(2)部门领导审批:请9天假
(3)大大领导VP审批:请9天假
----------------
(1)组长审批:请10天假
(2)部门领导审批:请10天假
(3)大大领导VP审批:请10天假
四、常见应用场景
- Java中,异常机制就是一种责任链模式。一个try可以对应多个catch,当第一个catch不匹配类型,则自动跳到第二个catch;
- Javascript语言中,事件的冒泡和捕获机制。Java语言中,事件的处理采用观察者模式。
- Servlet开发中,过滤器的链式处理。
- Struts2中,拦截器的调用也是典型的责任链模式。