责任链模式 (Chain of Responsibility Pattern)

news/2024/5/19 12:15:52 标签: 责任链模式, java, 设计模式, 开发语言
定义

责任链模式是一种行为型设计模式,用于在对象间建立一条处理请求的链。它允许多个对象有机会处理请求,从而减少请求的发送者和接收者之间的耦合。在责任链模式中,每个接收者包含对另一个接收者的引用,形成一条链。如果一个对象不能处理请求,它会将请求传递给链中的下一个对象,直至链的末端。

责任链模式由多个处理器(或接收者)组成,每个处理器决定自己是否处理请求或将其传递给链上的下一个处理器。这种模式实现了发送者和接收者之间的解耦,同时允许动态地调整链中的处理器。

责任链模式主要包含以下两个角色:

  1. 处理器(Handler)
    • 定义了处理请求的接口或抽象类,并通常持有对下一个处理器的引用。在其子类中,它可以选择处理请求或将请求传递给链上的下一个对象。
  2. 具体处理器(Concrete Handler)
    • 实现处理器接口的具体类。每个具体处理器决定它是否要处理请求,如果不处理,则将请求传递给链中的下一个对象。
解决的问题
  • 请求的发送者和接收者解耦
    • 在没有责任链模式的情况下,请求的发送者需要知道哪个接收者能够处理该请求,并直接调用相应的处理方法。责任链模式使得请求的发送者不需要直接与具体的接收者交互,从而解耦了发送者和接收者。
  • 动态处理请求
    • 责任链模式允许动态地重新组织和分配责任链上的处理者。这意味着可以在运行时改变请求的处理顺序或者增加新的处理者。
  • 简化对象间的连接
    • 通过责任链,可以减少对象间复杂的条件语句。在责任链模式中,请求沿着链传递,直到被处理。这避免了显式的多重条件判断。
  • 增加处理者的灵活性
    • 责任链模式让每个处理者都有机会处理请求。处理者可以决定是否处理请求,或者将请求传递给链上的下一个对象。
  • 分布式责任
    • 责任链模式允许多个对象处理请求,而不是只有一个对象负责所有的情况。这种分布式责任有助于代码的复用和扩展。
使用场景
  • 多个对象可以处理同一个请求,但具体的处理者在运行时才确定
    • 当一个请求可能由多个不同的对象处理,但是具体由哪个对象处理在运行时才决定时,责任链模式是理想的解决方案。
  • 请求的发送者不需要知道是谁处理了请求
    • 如果请求的发送者不需要知道请求最终由哪个对象处理,责任链模式可以将请求的发送和处理解耦。
  • 动态指定一组对象处理请求
    • 当需要动态地指定一系列对象来处理请求时,责任链模式提供了一种灵活的方法来组织这些对象。
  • 实现不同方式的请求处理
    • 在有多种处理方式,并且希望根据请求的类型或条件以不同的方式处理时,责任链模式能够提供足够的灵活性。
示例代码1-日志处理器
java">// 抽象处理器类
public 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);
        }
    }

    abstract protected void write(String message);
}

// 具体处理器实现
class ConsoleLogger extends Logger {
    public ConsoleLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {        
        System.out.println("Standard Console::Logger: " + message);
    }
}

// 客户端使用责任链
public class ChainPatternDemo {
    private static Logger getChainOfLoggers() {
        Logger errorLogger = new ErrorLogger(Logger.ERROR);
        Logger fileLogger = new FileLogger(Logger.DEBUG);
        Logger consoleLogger = new ConsoleLogger(Logger.INFO);

        errorLogger.setNextLogger(fileLogger);
        fileLogger.setNextLogger(consoleLogger);
        return errorLogger;
    }

    public static void main(String[] args) {
        Logger loggerChain = getChainOfLoggers();

        loggerChain.logMessage(Logger.INFO, "This is an information.");
        loggerChain.logMessage(Logger.DEBUG, "This is a debug level information.");
        loggerChain.logMessage(Logger.ERROR, "This is an error information.");
    }
}
示例代码2-审批流程
java">// 抽象处理器
abstract class Approver {
    protected Approver successor;

    public void setSuccessor(Approver successor) {
        this.successor = successor;
    }

    public abstract void processRequest(PurchaseRequest request);
}

// 具体处理器:经理
class Manager extends Approver {
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() < 1000) {
            System.out.println("Manager will approve the request of " + request.getAmount());
        } else if (successor != null) {
            successor.processRequest(request);
        }
    }
}

// 具体处理器:总监
class Director extends Approver {
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() < 5000) {
            System.out.println("Director will approve the request of " + request.getAmount());
        } else if (successor != null) {
            successor.processRequest(request);
        }
    }
}

// 具体处理器:CEO
class CEO extends Approver {
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() < 10000) {
            System.out.println("CEO will approve the request of " + request.getAmount());
        } else {
            System.out.println("Request of " + request.getAmount() + " needs a board meeting!");
        }
    }
}

// 请求类
class PurchaseRequest {
    private double amount;

    public PurchaseRequest(double amount) {
        this.amount = amount;
    }

    public double getAmount() {
        return amount;
    }
}

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

        manager.setSuccessor(director);
        director.setSuccessor(ceo);

        manager.processRequest(new PurchaseRequest(500));
        manager.processRequest(new PurchaseRequest(1500));
        manager.processRequest(new PurchaseRequest(5500));
    }
}
主要符合的设计原则
  • 开闭原则(Open-Closed Principle)
    • 责任链模式允许在不修改现有代码的情况下添加新的处理器。你可以添加新的处理类来扩展系统的功能,而无需修改现有的处理链或客户端代码。因此,系统对扩展是开放的,但对修改是封闭的。
  • 单一职责原则(Single Responsibility Principle)
    • 责任链模式中,每个处理器只负责处理特定类型的请求。这符合单一职责原则,因为每个处理器类只有一个理由发生变化——处理其特定的请求。
  • 里氏替换原则(Liskov Substitution Principle)
    • 责任链中的处理器通常遵循相同的接口。这意味着处理器的任何子类都可以替换其父类,而不影响系统的行为。
在JDK中的应用
  • java.util.logging.Logger
    • java.util.logging 包中,Logger 类使用责任链模式。日志消息可以在一个日志处理链中传递,每个处理器(如 ConsoleHandler, FileHandler)决定是否处理日志消息,并将消息传递到链中的下一个处理器。
  • Java Servlet Filters
    • 在Java Servlet API中,过滤器(Filter)使用责任链模式。请求和响应在多个过滤器之间传递,每个过滤器可以独立地处理请求或响应,或将其传递给链中的下一个过滤器。
  • javax.servlet.FilterChain
    • FilterChain 是Servlet API的一部分,它允许多个过滤器按顺序处理HTTP请求和响应。每个过滤器在链中都有机会处理请求和响应,或将其传递给链上的下一个过滤器。
在Spring中的应用
  • Spring Security的过滤器链
    • 在Spring Security中,安全过滤器链是责任链模式的一个显著例子。请求通过一系列的安全过滤器,每个过滤器执行特定的安全检查(如认证、授权等)。这些过滤器可以自定义和配置,形成一个处理安全的责任链。
  • Spring Web的拦截器
    • 在Spring MVC中,拦截器(Interceptor)提供了一种在处理HTTP请求时插入自定义逻辑的机制。拦截器可以形成一个拦截器链,每个拦截器按顺序执行,处理请求或响应,或将控制权传递给链中的下一个拦截器。
  • Spring AOP的通知链
    • 在Spring的面向切面编程(AOP)中,通知(Advice)可以被看作是责任链的一部分。不同的通知(如前置通知、后置通知、环绕通知等)可以按顺序应用于方法调用,形成一个通知链。


http://www.niftyadmin.cn/n/5206113.html

相关文章

持续格式刷

双击格式刷即可

命令模式 (Command Pattern)

定义 命令模式&#xff08;Command Pattern&#xff09;是一种行为型设计模式&#xff0c;它将一个请求封装为一个对象&#xff0c;从而允许用户使用不同的请求、队列或日志来参数化其他对象。命令模式也支持可撤销的操作。主要目的是将命令的发送者和接收者解耦&#xff0c;引…

PHP反序列化简单使用

注&#xff1a;比较简陋&#xff0c;仅供参考。 编写PHP代码&#xff0c;实现反序列化的时候魔法函数自动调用计算器 PHP反序列化 serialize(); 将对象序列化成字符串 unserialize(); 将字符串反序列化回对象 创建类 class Stu{ public $name; public $age; public $sex; publi…

从六个方面对比Go和Python的差异

您是否想过 Go 与 Python 之间的主要区别是什么&#xff1f;随着对软件开发人员的需求不断增加&#xff0c;选择哪种编码语言可能会很困难。 ​ 在此&#xff0c;我们将从六个方面对比Go和Python,探讨 Go 和 Python之间的差异。我们将讨论它们的特点、优缺点&#xff0c;以便…

Javascript中的宏任务与微任务

事件循环 JavaScript 语言的一大特点就是单线程&#xff0c;也就是说&#xff0c;同一个时间只能做一件事。为了协调事件、用户交互、脚本、UI 渲染和网络处理等行为&#xff0c;防止主线程的不阻塞&#xff0c;Event Loop 的方案应用而生。Event Loop 包含两类&#xff1a;一…

内网穿透隐秘隧道搭建

别低头&#xff0c;皇冠会掉&#xff1b;别流泪&#xff0c;贱人会笑。 本文首发于先知社区&#xff0c;原创作者即是本人 0x00 前言 构建内网隐蔽通道&#xff0c;从而突破各种安全策略限制&#xff0c;实现对目标服务器的完美控制。 当我们从外网成功获得攻击点的时候&…

代理模式 (Proxy Pattern)

定义&#xff1a; 代理模式&#xff08;Proxy Pattern&#xff09;是一种结构型设计模式&#xff0c;它通过提供一个代理&#xff08;或称代表&#xff09;对象来控制对另一个对象的访问。这种模式创建了一个代理对象&#xff0c;用来代表实际对象的功能&#xff0c;从而可以在…

2023年亚太数学建模大赛--A题(水果采摘机器人的图像识别功能)

中国是世界上最大的苹果生产国&#xff0c;年产量约为 3500 万吨。同时&#xff0c;中国也是世界上最大的苹果出口国&#xff0c;世界上每两个苹果中就有一个出口到国。世界上每两个苹果中就有一个来自中国&#xff0c;中国出口的苹果占全球出口量的六分之一以上。来自中国。中…