当前位置: 首页 > article >正文

十六、行为型(责任链模式)

责任链模式(Chain of Responsibility Pattern)

概念
责任链模式是一种行为型设计模式,它使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

责任链模式的核心思想是把请求的处理责任从一个对象转移到多个对象上。通过设置链式处理机制,多个对象可以动态参与请求处理,同时提高系统的可扩展性。


应用场景

  1. 多处理器处理请求:当一个请求可能被多个对象处理时,可以采用责任链模式将这些处理对象串联起来,沿着链条传递请求,直到找到合适的处理者。

  2. 避免复杂条件判断:如果在处理某些请求时,需要使用大量的条件语句(if-elseswitch-case),可以通过责任链模式将处理逻辑分散到不同的对象中,从而避免代码臃肿、难以维护。

  3. 日志过滤或权限控制:在日志记录或权限验证的场景中,不同的日志级别或权限控制可以使用责任链模式进行逐级处理。例如,日志系统可以根据不同的日志级别决定是否记录或输出日志信息。

  4. 审批流程:当一个请求需要经过多级审批时,责任链模式可以很好地实现逐级审批的机制。如果某一级不能处理,则传递给下一层。


注意点

  1. 请求必须能最终得到处理:责任链模式的链条中必须有一个对象能够处理请求,否则请求可能被丢失。

  2. 链条过长时可能影响性能:如果链条中包含的处理者对象很多,请求在链中传递的时间可能会较长,因此链的长度不宜过长。

  3. 容易出现不必要的调用:如果链条中的某些处理者不必要地调用了处理方法,可能会导致不必要的性能开销。


核心要素

  1. Handler(处理者接口/抽象类):定义处理请求的接口,同时包含设置下一个处理者的方法。

  2. ConcreteHandler(具体处理者):实现处理者接口的类,负责处理具体的请求,或者将请求传递给下一个处理者。

  3. Client(客户端):向链条上的处理者提交请求,由处理者决定如何处理该请求。


Java代码完整示例

示例:银行审批系统的责任链模式实现

// 抽象处理者
abstract class Approver {
    protected Approver nextApprover;  // 下一个处理者

    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }

    // 处理请求的抽象方法
    public abstract void approveRequest(int amount);
}

// 具体处理者:经理
class Manager extends Approver {
    @Override
    public void approveRequest(int amount) {
        if (amount <= 1000) {
            System.out.println("Manager approved request of amount " + amount);
        } else if (nextApprover != null) {
            nextApprover.approveRequest(amount);  // 传递给下一个处理者
        }
    }
}

// 具体处理者:总监
class Director extends Approver {
    @Override
    public void approveRequest(int amount) {
        if (amount <= 5000) {
            System.out.println("Director approved request of amount " + amount);
        } else if (nextApprover != null) {
            nextApprover.approveRequest(amount);  // 传递给下一个处理者
        }
    }
}

// 具体处理者:CEO
class CEO extends Approver {
    @Override
    public void approveRequest(int amount) {
        if (amount > 5000) {
            System.out.println("CEO approved request of amount " + amount);
        } else if (nextApprover != null) {
            nextApprover.approveRequest(amount);
        }
    }
}

// 客户端代码
public class ChainOfResponsibilityDemo {
    public static void main(String[] args) {
        Approver manager = new Manager();
        Approver director = new Director();
        Approver ceo = new CEO();

        // 设置责任链:经理 -> 总监 -> CEO
        manager.setNextApprover(director);
        director.setNextApprover(ceo);

        // 提交请求
        System.out.println("Requesting approval for amount 500:");
        manager.approveRequest(500);  // Manager handles this request

        System.out.println("\nRequesting approval for amount 3000:");
        manager.approveRequest(3000);  // Director handles this request

        System.out.println("\nRequesting approval for amount 10000:");
        manager.approveRequest(10000);  // CEO handles this request
    }
}

输出结果

Requesting approval for amount 500:
Manager approved request of amount 500

Requesting approval for amount 3000:
Director approved request of amount 3000

Requesting approval for amount 10000:
CEO approved request of amount 10000

各种变形用法完整示例

  1. 动态责任链

    在某些情况下,责任链的顺序可能并不是固定的。可以动态设置处理者链条,从而灵活地控制请求的传递顺序。

    代码示例:动态责任链

    public class DynamicChainDemo {
        public static void main(String[] args) {
            Approver manager = new Manager();
            Approver director = new Director();
            Approver ceo = new CEO();
    
            // 动态设置责任链
            director.setNextApprover(manager);  // 将总监设置为经理的下一个处理者
            ceo.setNextApprover(director);      // 将CEO设置为总监的下一个处理者
    
            // 提交请求
            System.out.println("Requesting approval for amount 2000:");
            ceo.approveRequest(2000);  // 由于链条是动态的,总监会首先处理
        }
    }
    

    输出结果

    Requesting approval for amount 2000:
    Director approved request of amount 2000
    
  2. 双向责任链

    有时请求可能需要在链条中向前或向后传递。在这种情况下,可以实现双向责任链。

    代码示例:双向责任链

    abstract class BiDirectionalApprover {
        protected BiDirectionalApprover nextApprover;
        protected BiDirectionalApprover prevApprover;
    
        public void setNextApprover(BiDirectionalApprover nextApprover) {
            this.nextApprover = nextApprover;
        }
    
        public void setPrevApprover(BiDirectionalApprover prevApprover) {
            this.prevApprover = prevApprover;
        }
    
        public abstract void approveRequest(int amount);
    }
    
    class ManagerBiDirectional extends BiDirectionalApprover {
        @Override
        public void approveRequest(int amount) {
            if (amount <= 1000) {
                System.out.println("Manager approved request of amount " + amount);
            } else if (nextApprover != null) {
                nextApprover.approveRequest(amount);
            } else if (prevApprover != null) {
                prevApprover.approveRequest(amount);  // 向前传递
            }
        }
    }
    
    // 双向链条示例
    public class BiDirectionalChainDemo {
        public static void main(String[] args) {
            BiDirectionalApprover manager = new ManagerBiDirectional();
            BiDirectionalApprover director = new DirectorBiDirectional();
            BiDirectionalApprover ceo = new CEO();
    
            // 设置链条
            manager.setNextApprover(director);
            director.setPrevApprover(manager);
    
            // 请求
            manager.approveRequest(2000);
        }
    }
    
  3. 链式日志处理

    在日志系统中,可以使用责任链模式实现日志的逐级过滤。例如,只输出大于某个级别的日志。

    代码示例:链式日志处理

    // 抽象日志处理者
    abstract class Logger {
        public static int INFO = 1;
        public static int DEBUG = 2;
        public static int ERROR = 3;
    
        protected int level;
        protected Logger nextLogger;
    
        public void setNextLogger(Logger nextLogger) {
            this.nextLogger = nextLogger;
        }
    
        public void logMessage(int level, String message) {
            if (this.level <= level) {
                write(message);
            }
            if (nextLogger != null) {
                nextLogger.logMessage(level, message);
            }
        }
    
        protected abstract void write(String message);
    }
    
    // 具体日志处理者
    class ConsoleLogger extends Logger {
        public ConsoleLogger(int level) {
            this.level = level;
        }
    
        @Override
        protected void write(String message) {
            System.out.println("Console Logger: " + message);
        }
    }
    
    class FileLogger extends Logger {
        public FileLogger(int level) {
            this.level = level;
        }
    
        @Override
        protected void write(String message) {
            System.out.println("File Logger: " + message);
        }
    }
     // 日志系统示例
    public class LoggerDemo {
        public static void main(String[] args) {
            Logger consoleLogger = new ConsoleLogger(Logger.INFO);
            Logger fileLogger = new FileLogger(Logger.ERROR);
    
            // 设置链条
            consoleLogger.setNextLogger(fileLogger);
    
            consoleLogger.logMessage(Logger.INFO, "This is an information.");
            consoleLogger.logMessage(Logger.ERROR, "This is an error message.");
        }
    }
    

通过这些示例,可以灵活运用责任链模式,根据业务需求构建多种责任链。


http://www.kler.cn/news/364041.html

相关文章:

  • FPGA第 13 篇,使用 Xilinx Vivado 创建项目,点亮 LED 灯,Vivado 的基本使用(点亮ZYNQ-7010开发板的LED灯)
  • 【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (四):状态码的使用
  • 面经之一:Synchronized与ReentrantLock区别
  • 知乎付费投流怎么做?如何投放知乎广告?
  • PDF.js的使用及其跨域问题解决
  • GraphLLM:基于图的框架,通过大型语言模型处理数据
  • 2024年9月中国电子学会青少年软件编程(Python)等级考试试卷(三级)答案 + 解析
  • PHP企业门店订货通进销存系统小程序源码
  • 定位中的信号干扰与噪声处理
  • 手机群控软件苹果iOS批量控制进化历程 解析及最新动态
  • 普通数组矩阵
  • 西南大学软件专硕考研难度分析!
  • 配置观察端口
  • 【主机漏洞扫描常见修复方案】:Tomcat安全(机房对外Web服务扫描)
  • 图集短视频去水印云函数开发实践——小红书
  • 小白投资理财 - 解读市销率,市现率
  • 新电脑Win11家庭中文版跳过联网激活方法(教程)
  • Go 语言教程:8.数组
  • 毕业设计 基于STM32单片机健康检测/老人防跌倒系统 心率角度检测GSM远程报警 (程序+原理图+元件清单全套资料)
  • 基于springboot企业微信SCRM管理系统源码带本地搭建教程
  • python学习之路 - python进阶【闭包、装饰器、设计模式、多线程、socket、正则表达式】
  • centos-LAMP搭建与配置(论坛网站)
  • 20241024拿掉飞凌OK3588-C的开发板linux R4启动时的LOGO
  • NSSCTF
  • 大话红黑树之(2)源码讲解TreeMap-Java
  • 探索人工智能在自然语言处理中的应用