一、概念
责任链,顾名思义,就是用来处理相关事务责任的一条执行链,执行链上有多个节点,每个节点都有机会(条件匹配)处理请求事务,如果某个节点处理完了就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。
简单的说就是一个请求有多个对象来处理,这些对象是一条链,但具体由哪个对象来处理,根据条件判断来确定,如果不能处理会传递给该链中的下一个对象,直到有对象处理它为止。
例如现实生活中的请假,你是一个打工人,你发起一个请假请求,三天以内由你直接领导处理,3-7天由你经理处理,7天以上由总监处理的这种情况
二、使用场景
- 有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定。
- 在不明确指定接受者的情况下,向多个对象中的一个提交一个请求。
- 可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求。
三、主要解决
职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
四、模式的结构
- 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
- 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
- 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
五、责任链模式的优缺点
优点:
1、降低耦合度。它将请求的发送者和接收者解耦。
2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
4、增加新的请求处理类很方便。
缺点:
1、不能保证请求一定被接收。
2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
3、可能不容易观察运行时的特征,有碍于除错。
六、代码结构
public class DemoClient{
public static void main(String[] args) {
//组装责任链
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
handler1.setNext(handler2);
//提交请求
handler1.handleRequest();
}
}
//抽象处理者角色
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 () {
//do something
} else {
if (getNext() != null) {
getNext().handleRequest(request);
} else {
//do something
}
}
}
}
//具体处理者角色2
class ConcreteHandler2 extends Handler {
public void handleRequest(String request) {
if () {
//do something
} else {
if (getNext() != null) {
getNext().handleRequest(request);
} else {
//do something
}
}
}
}
七、代码案例
package responsibility;
/**
* @Package: responsibility
* @ClassName: Leader
* @Author: tanp
* @Description: 抽象处理者角色 请假责任链抽象处理类
* @Date: 2020/11/16 15:46
*/
public abstract class Leader {
/**下一个处理节点*/
Leader leader;
/**设置下一节点*/
public void setNext(Leader leader){
this.leader = leader;
}
/**处理请假的请求,子类实现*/
abstract void handlerRequest(MyRequest myRequest);
}
package responsibility;
/**
* @Package: responsibility
* @ClassName: Director
* @Author: tanp
* @Description: 具体处理者 主管
* @Date: 2020/11/16 15:50
*/
public class Director extends Leader{
@Override
void handlerRequest(MyRequest myRequest) {
if (myRequest.getDays() <= 3) {
System.out.println("主管批准您请假" + myRequest.getDays() + "天。");
} else {
if (this.leader != null) {
this.leader.handlerRequest(myRequest);
} else {
System.out.println("不批准该假条!");
}
}
}
}
package responsibility;
/**
* @Package: responsibility
* @ClassName: Manager
* @Author: tanp
* @Description: 具体处理者 经理
* @Date: 2020/11/16 15:56
*/
public class Manager extends Leader{
@Override
void handlerRequest(MyRequest myRequest) {
if (myRequest.getDays() <= 7) {
System.out.println("经理批准您请假" + myRequest.getDays() + "天。");
} else {
if (this.leader != null) {
this.leader.handlerRequest(myRequest);
} else {
System.out.println("不批准该假条!");
}
}
}
}
package responsibility;
/**
* @Package: responsibility
* @ClassName: Boss
* @Author: tanp
* @Description: 具体处理类 老板
* @Date: 2020/11/16 15:57
*/
public class Boss extends Leader{
@Override
void handlerRequest(MyRequest myRequest) {
if (myRequest.getDays() <= 20) {
System.out.println("老板批准您请假" + myRequest.getDays() + "天。");
} else {
if (this.leader != null) {
this.leader.handlerRequest(myRequest);
} else {
System.out.println("不批准该假条!");
}
}
}
}
package responsibility;
/**
* @Package: responsibility
* @ClassName: MyRequest
* @Author: tanp
* @Description: 请假请求
* @Date: 2020/11/16 11:44
*/
public class MyRequest {
private final String name;
private final int days;
private MyRequest(Build build){
this.days = build.days;
this.name = build.name;
}
public static class Build{
private String name;
private int days;
public Build setDays(int days){
this.days = days;
return this;
}
public Build setName(String name){
this.name = name;
return this;
}
public MyRequest build(){
return new MyRequest(this);
}
}
public int getDays() {
return days;
}
}
package responsibility;
/**
* @Package: responsibility
* @ClassName: DemoClient
* @Author: tanp
* @Description: ${description}
* @Date: 2020/11/16 15:59
*/
public class DemoClient {
public static void main(String[] args) {
//组装责任链
Leader director = new Director();
Leader manager = new Manager();
Leader boss = new Boss();
director.setNext(manager);
manager.setNext(boss);
//新建请求
MyRequest myRequest = new MyRequest.Build().setDays(8).setName("小明").build();
//提交请求
director.handlerRequest(myRequest);
}
}
八、在实际中的应用
①try-catch语句:
每一个catch语句是根据Exception异常类型进行匹配的,一般会有多个catch语句,就形成了一个责任链;此时如果有一个catch语句与当前所要处理的异常Exception符合时,该Exception就会交给相应的catch语句进行处理,之后的catch语句就不会再执行了。
②异常处理机制:
方法的调用构成了一个栈,当栈顶的方法产生异常时,需要将异常抛出,被抛出的异常沿着调用栈向下发展,寻找一个处理的块,被栈顶抛出的方法作为一个请求,而调用栈上的每一个方法就相当于一个handler,该Handler即可以选择自行处理这个被抛出的异常,也可以选择将异常沿着调用栈传递下去。
异常:请求
调用栈中的每一级:Handler
调用栈中的handler:责任链
栈底元素:上一级元素的直接后继