设计模式之责任链模式-CSDN博客

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

 

什么是责任链模式

        在一些业务场景下为了避免请求发送者与多个请求处理者耦合在一起于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链当有请求发生时可将请求沿着这条链传递直到有对象处理它为止。在责任链模式中多个处理器也就是刚刚定义中说的“接收对象”依次处理同一个请求。一个请求先经过A处理器处理然后再把请求传递给B处理器B处理器处理完后再传递给C处理器以此类推形成一个链条。链条上的每个处理器各自承担各自的处理职责所以叫作职责链模式。

责任链模式的核心角色有哪些

  1. 抽象处理者(Handler)定义一个处理请求的接口通常包含一个指向下一个处理者的引用。
  2. 具体处理者(ConcreteHandler)实现抽象处理者接口负责处理它所能处理的请求如果自己不能处理就将请求传递给下一个处理者。
  3. 客户类Client角色创建处理链并向链头的具体处理者对象提交请求它不关心处理细节和请求的传递过程。

责任链模式如何实现

        这里以工厂的流水线生产为例来分析研究一下责任链模式如何实现。

需求描述

        假设一台手机的各种零部件已经制造完成具体的手机的组装过程是这样的

  1. 主板安装
  2. 电池安装
  3. 屏幕安装
  4. 通电测试

如果写一段程序来模拟这个组装过程选择使用责任链模式来实现应该怎么实现呢

实现方法

1、声明一个抽象的分步组装的处理类定义抽象的组装方法和指向下一步的处理者的引用

/**
 * 抽象的分步组装处理类
 */
public abstract class AbstractHandler {
    private AbstractHandler abstractHandler;
    public AbstractHandler getAbstractHandler() {
        return abstractHandler;
    }
    public void next(AbstractHandler abstractHandler) {
        this.abstractHandler = abstractHandler;
    }
    public abstract void make();
}

2、声明具体的处理者即主板安装的处理者继承了抽象的分步组装处理器实现抽象的组装方法即主板的安装

/**
 * 主板安装
 */
public class MotherboardHandler extends AbstractHandler {
    @Override
    public void make() {
        System.out.println("主机安装完成");
        if (this.getAbstractHandler() != null) {
            this.getAbstractHandler().make();
        }
    }
}

3、声明第二具体的处理者即电池安装的处理者继承了抽象的分步组装处理器实现抽象的组装方法即电池的安装

/**
 * 电池安装
 */
public class BatteryHandler extends AbstractHandler{
    @Override
    public void make() {
        System.out.println("电池组装完成");
        if (this.getAbstractHandler() != null) {
            this.getAbstractHandler().make();
        }
    }
}

4、声明具体的处理者即屏幕安装的处理者继承了抽象的分步组装处理器实现抽象的组装方法即屏幕的安装


/**
 * 屏幕安装
 */
public class ScreenHandler extends AbstractHandler{
    @Override
    public void make() {
        System.out.println("屏幕安装完成");
        if (this.getAbstractHandler() != null) {
            this.getAbstractHandler().make();
        }
    }
}

5、声明具体的处理者即整机上电测试的处理者继承了抽象的分步组装处理器实现抽象的组装方法即上电测试

/**
 * 上电测试
 */
public class TestHandler extends AbstractHandler {
    @Override
    public void make() {
        System.out.println("上电测试通过");
        if (this.getAbstractHandler() != null) {
            this.getAbstractHandler().make();
        }
    }
}

6、声明一个客户端也就是手机组装生产线主要业务也就是把组装过程的每一步整合起来这样一条完整的手机组装生产线就搭建好了可以开始生产活动了

/**
 * 生产线
 */
public class ProductLine {
    public static void main(String[] args) {
        AbstractHandler step1=new MotherboardHandler();
        AbstractHandler step2=new BatteryHandler();
        AbstractHandler step3=new ScreenHandler();
        AbstractHandler step4=new TestHandler();
        step1.next(step2);
        step2.next(step3);
        step3.next(step4);
        step1.make();
    }
}

如何扩展

        科技进步了手机不仅能接电话和打电话还能拍照那么原来的手机组装生产线就需要升级增加摄像头的组装。面对这样的扩展需求应该怎么实现呢很简单往下看

1、增加一个工位即声明一个摄像头安装的处理类同样继承于抽象的分步组装处理器实现抽象的组装方法即摄像头安装

/**
 * 报像头安装
 */
public class CameraHandler extends AbstractHandler{
    @Override
    public void make() {
        System.out.println("摄像头安装完成");
        if (this.getAbstractHandler() != null) {
            this.getAbstractHandler().make();
        }
    }
}

2、原来的生产线的工作顺序调整一下在主机安装完成后增加一步摄像头的组装就可以了原来的其他步骤的工作逻辑不变完全符合开闭原则。

/**
 * 生产线
 */
public class ProductLine {
    public static void main(String[] args) {
        AbstractHandler step1=new MotherboardHandler();
        AbstractHandler step1_2=new CameraHandler();
        AbstractHandler step2=new BatteryHandler();
        AbstractHandler step3=new ScreenHandler();
        AbstractHandler step4=new TestHandler();
        step1.next(step2);
        step1.next(step1_2);
        step1_2.next(step2);
        step2.next(step3);
        step3.next(step4);
        step1.make();
    }
}

责任链模式的适用场景

        责任链模式适用于处理具有依次顺序、多个步骤的场景如

  1. 订单处理系统在订单处理系统中订单需要依次经过多个环节的处理比如校验订单信息、生成订单号、计算订单金额、库存扣减等等。每个环节都有可能出现异常情况需要进行相应的处理。使用责任链模式可以将每个处理环节封装成一个处理器通过责任链将订单依次传递给这些处理器进行处理直到订单处理完成。这样可以使得订单处理流程更加清晰和灵活。
  2. 日志记录系统在一个日志记录系统中日志需要经过多个过滤器进行处理比如按照日志级别进行过滤、按照关键字进行过滤、按照时间进行过滤等等。每个过滤器都有自己的处理逻辑和优先级需要根据配置来确定日志经过哪些过滤器进行处理。使用责任链模式可以将每个过滤器封装成一个处理器通过责任链将日志依次传递给这些过滤器进行处理直到所有过滤器都处理完毕。这样可以使得日志过滤流程更加灵活和可配置。
  3. 用户登录验证手机验证码登录需要进行用户是否存在、验证码是否为空、验证码是否正确、用户是否锁定、用户是否被禁用等校验。这些校验都可以封装成处理器通过责任链依次传递给这些处理器进行处理。

责任链模式在Spring中的应用

责任链模式在Spring中有很多应用场景

  1. Spring的异常处理Spring的异常处理机制采用了责任链模式通过定义不同的异常处理器将不同的异常类型传递给不同的处理器进行处理。这样可以使得异常处理更加灵活和可配置。
  2. Spring的拦截器Spring的拦截器使用了责任链模式通过定义不同的拦截器将请求依次传递给这些拦截器进行处理。这样可以使得请求处理流程更加清晰和灵活。
  3. Spring的AOP实现Spring的AOP实现也使用了责任链模式通过定义不同的切面Aspect将请求依次传递给这些切面进行处理。这样可以使得代码更加清晰和易于维护。
  4. Spring的HandlerInterceptor在Spring MVC框架中可以使用HandlerInterceptor来拦截请求并处理请求。每个HandlerInterceptor都可以看作是一个处理器通过责任链将请求依次传递给这些处理器进行处理。这样可以使得请求处理流程更加灵活和可配置。

总结

优点

  1. 降低对象之间的耦合度责任链模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构发送者和接收者也无须拥有对方的明确信息。
  2. 增强系统的可扩展性可以根据需要增加新的请求处理类满足开闭原则。
  3. 增强给对象指派职责的灵活性当工作流程发生变化时可以动态地改变链内的成员或者调动它们的次序也可动态地新增或者删除责任。
  4. 简化对象之间的连接每个对象只需保持一个指向其后继者的引用不需保持其他所有处理者的引用这避免了使用众多的if或者if···else语句。
  5. 责任分担每个类只需要处理自己该处理的工作不该处理的传递给下一个对象完成明确各类的责任范围符合类的单一职责原则。

缺点

  1. 性能问题每个请求都是从链表头遍历到链表尾特别是链表比较长的时候性能是一个非常大的问题。
  2. 调试不方便特别是链表比较长环节比较多的时候由于采用了类似递归的方式调试的时候可能逻辑比较复杂。

        在使用责任链模式时需要注意链中节点的数量需要控制避免出现超长链的情况。一般做法是在Handler中设置一个最大的节点数量在setNext()方法中判断是否已经是超过其阈值超过则不允许建立避免无意识的破坏系统性能。

 

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6