1.为什么会有责任链?
1.面试会问道
2.代替if else ( 策略模式 + 工厂模式 是最好的 )
2.使用场景
1.Netty 中的 Pipeline 和 ChannelHandler 通过责任链设计模式来组织代码逻辑
2.Spring Security 使用责任链模式,可以动态地添加或删除责任(处理 request 请求)
3.Spring AOP 通过责任链模式来管理 Advisor
4.Dubbo Filter 过滤器链也是用了责任链模式(链表),
可以对方法调用做一些过滤处理,譬如超时(TimeoutFilter),异常(ExceptionFilter), Token(TokenFilter)等
3.简介
职责链模式主要包含以下角色。
- 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
- 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
- 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与被处理;理解责任链模式应当理解其模式,而不是其具体实现。责任链模式的独到之处是将其节点处理者组合成了链式结构,并允许节点自身决定是否进行请求处理或转发,相当于让请求流动起来
4.缺点/优点
优点
责任链模式非常显著的优点是将请求和处理分开。请求者可以不用知道是谁处理的,处
理者可以不用知道请求的全貌(例如在J2EE项目开发中,可以剥离出无状态Bean由责任链处
理),两者解耦,提高系统的灵活性。
缺点
责任链有两个非常显著的缺点:一是性能问题,每个请求都是从链头遍历到链尾,特别
是在链比较长的时候,性能是一个非常大的问题。二是调试不很方便,特别是链条比较长,
环节比较多的时候,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂。
一般我们可以在 `Handler` 中设置一个最大节点数量,在 `setNext` 方法中判断是否已经超过最大节点数,超过则不允许继续添加处理者,避免无意识的破坏系统性能。
5.案例
需求:吴签的日常安排,周末到工作日,并输出
3步走:
1.创建星期的抽象处理者 WeekHandler
2.创建具体的处理者 MondayConcrete TuesdayConcrete WednesdayConcrete 。。。。
3.客户类 StudentClient
1.创建星期的抽象处理者
public abstract class WeekHandler {
private WeekHandler next;
public void setNext(WeekHandler next) {
this.next = next;
}
public WeekHandler getNext() {
return next;
}
//处理请求的方法
public abstract String handleRequest(String day);
}
2.创建具体的处理者
public class TuesdayConcrete extends WeekHandler {
@Override
public String handleRequest(String day) {
if ("星期一".equals(day)) {
return "星期一:你需要去上舞蹈课";
} else {
if (getNext() != null) {
return getNext().handleRequest(day);
} else {
return "输入参数错误";
}
}
}
}
public class MondayConcrete extends WeekHandler {
@Override
public String handleRequest(String day) {
if ("星期二".equals(day)) {
return "星期二:你需要去上钢琴课";
} else {
if (getNext() != null) {
return getNext().handleRequest(day);
} else {
return "输入参数错误";
}
}
}
}
public class WednesdayConcrete extends WeekHandler {
@Override
public String handleRequest(String day) {
if ("星期三".equals(day)) {
return "星期三:休息的一天";
} else {
if (getNext() != null) {
return getNext().handleRequest(day);
} else {
return "输入参数错误";
}
}
}
}
3.客户类
public class StudentClient {
public static void main(String[] args) {
WeekHandler weekHandler1 = new TuesdayConcrete();
WeekHandler weekHandler2 = new MondayConcrete();
WeekHandler weekHandler3 = new WednesdayConcrete();
weekHandler1.setNext(weekHandler2);
weekHandler2.setNext(weekHandler3);
//提交请求
String reg1 = weekHandler1.handleRequest("星期一");
String reg2 = weekHandler1.handleRequest("星期二");
String reg3 = weekHandler1.handleRequest("星期三");
System.out.println(reg1);
System.out.println(reg2);
System.out.println(reg3);
}
}
效果
星期一:你需要去上舞蹈课
星期二:你需要去上钢琴课
星期三:休息的一天