设计模式之职责链模式

1. 职责链模式(Chain of Responsibility Pattern)

        在职责链模式中,多个处理器依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。

1.1. 模式架构

  • 抽象处理者(Handler):定义一个处理请求的接口,包含抽象处理方法一个后继连接(链上的每个处理者都有一个成员变量来保存对于下一处理者的引用) 。
  • 具体处理者(Concrete Handler):实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  • 请求者(Client):创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

1.2. 示例实现代码

        Trouble类是表示发生问题的类,number是问题编号。通过getNumber来获取问题编号。

        问题的大小从升序排序为:1 < 2 < 3 < 4

        处理者处理问题的能力升序排序为:HandlerA < HandlerB < HandlerC < HandlerD

public class Trouble {
    private String number;//问题编号

    public Trouble(String number) {
        this.number = number;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    @Override
    public String toString() {
        return "Trouble{" +
                "number='" + number + '\'' +
                '}';
    }
}

抽象处理者(Handler):

Handler

public abstract class Handler{
    //处理器执行链路
    protected Handler successor = null;

    //设置下一个处理请求的处理者对象
    public void setSuccessor(Handler successor){
        this.successor = successor;
    }

    //处理的方法,具体处理者需根据不同需求进行实现
    public abstract void handle(Trouble trouble);
}

具体处理者(Concrete Handler):

HandlerA

public class HandlerA extends Handler {
   //具体处理者的实现方法
    @Override
    public void handle(Trouble trouble) {
        System.out.print("HandlerA 执行代码逻辑! 处理: " +
                trouble.getNumber());
        trouble.setNumber(trouble.getNumber().replace("1", ""));
        System.out.println(",处理完的结果为:" + trouble.getNumber());
        if (successor != null) {
            successor.handle(trouble);
        }else {
            System.out.println("执行终止");
        }
    }
}

HandlerB

public class HandlerB extends Handler {
    //具体处理者的实现方法
    @Override
    public void handle(Trouble trouble) {
        System.out.print("HandlerB 执行代码逻辑! 处理: " +
                trouble.getNumber());
        trouble.setNumber(trouble.getNumber().replace("2", ""));
        System.out.println(",处理完的结果为:" + trouble.getNumber());
        if (successor != null) {
            successor.handle(trouble);
        }else {
            System.out.println("执行终止");
        }
    }
}

HandlerC

public class HandlerC extends Handler {
   //具体处理者的实现方法
    @Override
    public void handle(Trouble trouble) {
        System.out.print("HandlerC 执行代码逻辑! 处理: " +
                trouble.getNumber());
        trouble.setNumber(trouble.getNumber().replace("3", ""));
        System.out.println(",处理完的结果为:" + trouble.getNumber());
        if (successor != null) {
            successor.handle(trouble);
        }else {
            System.out.println("执行终止");
        }
    }
}

HandlerD

public class HandlerD extends Handler {
   //具体处理者的实现方法
    @Override
    public void handle(Trouble trouble) {
        System.out.print("HandlerD 执行代码逻辑! 处理: " +
                trouble.getNumber());
        trouble.setNumber(trouble.getNumber());
        System.out.println(",处理完的结果为:" + trouble.getNumber());
        if (successor != null) {
            successor.handle(trouble);
        }else {
            System.out.println("执行终止");
        }
    }
}

请求者(Client):

public class Client {
    public static void main(String[] args) {
        //包含1234的问题
        Trouble trouble = new Trouble("1234");
        //包含123的问题
        Trouble trouble2 = new Trouble("123");
        
        Handler h1 = new HandlerA();
        Handler h2 = new HandlerB();
        Handler h3 = new HandlerC();
        //设置处理器执行链路
        h1.setSuccessor(h2);
        h2.setSuccessor(h3);
        //执行
        h1.handle(trouble);
    }
}

执行结果:

HandlerA 执行代码逻辑! 处理: 1234,处理完的结果为:234

HandlerB 执行代码逻辑! 处理: 234,处理完的结果为:34

HandlerC 执行代码逻辑! 处理: 34,处理完的结果为:4

执行终止

        在以上示例代码中,Handler抽象类定义了处理的抽象方法和后续的执行连接处理对象,而HandlerA~D是对应不同的具体处理类,每个类可以解决不同级别的问题,请求者可以设置执行链路,当一个含有不同等级的问题要处理时,会根据执行链路进行执行,若当前处理类无法处理该问题,则让下一个处理对象判断是否能处理,执行全部处理完毕。

1.3. 优缺点

优点

  • 降低耦合度:请求者不需要知道是哪个具体的处理者处理请求,降低了发送者和接收者之间的耦合度。
  • 灵活性增强:可以动态地增加或修改处理请求的链条,更容易地根据需要改变处理流程。
  • 简化对象:每个具体处理者只需关注自己责任范围内的处理逻辑,符合单一职责原则。

缺点

  • 请求不一定被处理:如果请求到达链条末端仍然没有处理者能够处理,可能会导致请求未被处理的情况。
  • 性能问题:请求可能会经过多个处理者才能被处理,特别是在链条较长时,可能会影响性能。
  • 调试复杂:链条中每个具体处理者的执行顺序不确定,难以调试。

在生活中比较常见的应用模式有:

1、在运行时需要动态使用多个关联对象来处理同一次请求时,比如各种流程执行:请假流程、员工入职流程。

2、需要动态更换处理对象时。比如,工单处理系统、网关 API 过滤规则系统等。

3、电商网站活动方式,一般分为满减送、限时折扣、包邮活动,拼团等可以采用策略模式

        职责链模式常被用在框架开发中,用来实现框架的过滤器、拦截器功能,让框架的使用者在不修改源码的情况下,添加新的过滤拦截功能。

相关推荐

  1. 设计模式职责模式(下)

    2024-07-11 00:54:03       37 阅读
  2. 设计模式 -职责模式

    2024-07-11 00:54:03       55 阅读
  3. 设计模式--职责模式

    2024-07-11 00:54:03       22 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-11 00:54:03       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-11 00:54:03       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-11 00:54:03       57 阅读
  4. Python语言-面向对象

    2024-07-11 00:54:03       68 阅读

热门阅读

  1. 基于Gunicorn、Flask和Docker的高并发部署实践

    2024-07-11 00:54:03       22 阅读
  2. 【力扣C语言】每日一题—第69题,X的平方根

    2024-07-11 00:54:03       20 阅读
  3. 【Git】本地版本控制

    2024-07-11 00:54:03       23 阅读
  4. 【Cookie 在 Spring Boot 中的实现】

    2024-07-11 00:54:03       21 阅读
  5. SQL的时间格式和文本灵活转换

    2024-07-11 00:54:03       27 阅读
  6. ubuntu22 设置开机直接登录桌面

    2024-07-11 00:54:03       22 阅读
  7. Sqlmap中文使用手册 - Options模块参数使用

    2024-07-11 00:54:03       17 阅读
  8. GIT基本概念以及简单使用方法

    2024-07-11 00:54:03       22 阅读