2.责任链模式

570 阅读3分钟

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.简介

职责链模式主要包含以下角色。

  1. 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
  2. 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  3. 客户类(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);

    }
}

效果

星期一:你需要去上舞蹈课

星期二:你需要去上钢琴课

星期三:休息的一天