目录
- 1. 简介
- 2. 代码
- 2.1 AbstractLogger(抽象处理者)
- 2.2 InfoLogger (具体处理者)
- 2.3 DebugLogger (具体处理者)
- 2.4 ErrorLogger (具体处理者)
- 2.5 Test (测试)
- 2.6 运行结果
- 2.7 其他
- 3. 使用场景
- 4. 优缺点
- 5. 总结
1. 简介
责任链模式(Chain of Responsibility Pattern) 是一种行为型设计模式,旨在解决请求发送者和接收者之间的耦合问题。通过将多个对象连接成一条链,请求沿着这条链传递,直到某个对象决定处理该请求为止。这种模式允许系统动态地重新组织和分配责任,而不会影响客户端。
责任链模式的结构:
抽象处理者(Handler) :定义处理请求的接口,并包含对后继处理者的引用。抽象处理者通常定义一个处理请求的方法,可以实现后继链。
具体处理者(ConcreteHandler) :实现抽象处理者的接口,负责处理用户请求。如果当前处理者无法处理请求,则会将请求转发给下一个处理者。
2. 代码
设置三个等级的日志,如果加入的警告等级高,会触发更多的日志
2.1 AbstractLogger(抽象处理者)
java">public abstract class AbstractLogger {public static int INFO = 1;public static int DEBUG = 2;public static int ERROR = 3;protected int level;protected AbstractLogger nextLogger;public void setNextLogger(AbstractLogger 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);
}
2.2 InfoLogger (具体处理者)
java">public class InfoLogger extends AbstractLogger{public InfoLogger(int level){this.level = level;}@Overrideprotected void write(String message){System.out.println("InfoLogger: " + message);}
}
2.3 DebugLogger (具体处理者)
java">public class DebugLogger extends AbstractLogger{public DebugLogger(int level){this.level = level;}@Overrideprotected void write(String message){System.out.println("Debug Logger: " + message);}
}
2.4 ErrorLogger (具体处理者)
java">public class ErrorLogger extends AbstractLogger{public ErrorLogger(int level){this.level = level;}@Overridepublic void write(String message){System.out.println("Error Console::Logger: " + message);}
}
2.5 Test (测试)
java">public class Test {// 创建责任链public static AbstractLogger getChainOfLoggers() {InfoLogger infoLogger = new InfoLogger(AbstractLogger.INFO);DebugLogger debugLogger = new DebugLogger(AbstractLogger.DEBUG);ErrorLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);infoLogger.setNextLogger(debugLogger);debugLogger.setNextLogger(errorLogger);return infoLogger;}public static void main(String[] args){AbstractLogger loggerChain = Test.getChainOfLoggers();loggerChain.logMessage(AbstractLogger.INFO, "This is an information.");System.out.println("-------------------");loggerChain.logMessage(AbstractLogger.DEBUG, "This is an debug level information.");System.out.println("-------------------");loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information.");}
}
2.6 运行结果
InfoLogger: This is an information.
-------------------
InfoLogger: This is an debug level information.
Debug Logger: This is an debug level information.
-------------------
InfoLogger: This is an error information.
Debug Logger: This is an error information.
Error Console::Logger: This is an error information.
2.7 其他
java">package behavioral.chain;// 抽象处理器
abstract class Approver {protected Approver successor; // 后继处理者public void setSuccessor(Approver successor) {this.successor = successor;}public abstract void processLeaveApplication(LeaveApplication application);
}// 具体处理器 - 班长
class Monitor extends Approver {@Overridepublic void processLeaveApplication(LeaveApplication application) {if (application.getDays() <= 1) {System.out.println("班长批准了请假申请");} else if (successor != null) {successor.processLeaveApplication(application);} else {System.out.println("没有人批准请假申请");}}
}// 具体处理器 - 辅导员
class Counselor extends Approver {@Overridepublic void processLeaveApplication(LeaveApplication application) {if (application.getDays() <= 3) {System.out.println("辅导员批准了请假申请");} else if (successor != null) {successor.processLeaveApplication(application);} else {System.out.println("没有人批准请假申请");}}
}// 具体处理器 - 学生办
class StudentOffice extends Approver {@Overridepublic void processLeaveApplication(LeaveApplication application) {if (application.getDays() <= 7) {System.out.println("学生办批准了请假申请");} else {System.out.println("没有人批准请假申请");}}
}// 请假申请类
class LeaveApplication {private int days;public LeaveApplication(int days) {this.days = days;}public int getDays() {return days;}
}// 客户端代码
public class Client {public static void main(String[] args) {// 创建处理链Approver monitor = new Monitor();Approver counselor = new Counselor();Approver studentOffice = new StudentOffice();monitor.setSuccessor(counselor);counselor.setSuccessor(studentOffice);// 提交请假申请LeaveApplication application1 = new LeaveApplication(1);monitor.processLeaveApplication(application1); // 班长批准LeaveApplication application2 = new LeaveApplication(2);monitor.processLeaveApplication(application2); // 班长批准LeaveApplication application3 = new LeaveApplication(4);monitor.processLeaveApplication(application3); // 辅导员批准LeaveApplication application4 = new LeaveApplication(8);monitor.processLeaveApplication(application4); // 学生办批准}
}
运行结果:
班长批准了请假申请
辅导员批准了请假申请
学生办批准了请假申请
没有人批准请假申请
3. 使用场景
- 多个对象处理同一请求:当一个请求需要由多个对象按顺序处理时,责任链模式非常有用。例如,在日志记录系统中,不同级别的日志(如INFO、ERROR、DEBUG)可以由不同的处理器处理。同样,在审批流程中,一个请求可以由多个审批者依次审批,直到最终批准或拒绝。
- 动态处理流程:当请求的处理流程不确定,且每个处理节点是否处理请求都不确定时,责任链模式提供了一种灵活的机制。例如,在Web应用开发中,可以通过责任链模式实现过滤器链式处理,每个过滤器负责处理特定的请求类型。
- 权限校验和拦截器设计:在权限校验的登录拦截器中,责任链模式可以用于动态地添加或删除处理者,以适应业务需求的变化。此外,责任链模式也被应用于拦截器设计,如Cicada框架中的拦截器调用。
- 事件处理系统:在GUI事件处理中,责任链模式可以用于处理用户交互事件,每个事件处理器负责处理特定的用户交互事件。
- 安全防护:在安全场景中,责任链模式可以用于防止XSS攻击,通过创建一个FilterChain,包含多个过滤器,每个过滤器负责处理请求并传递给下一个过滤器,直到所有过滤器完成处理。
- 生产流程和报销审批流程:在生产线中,责任链模式可以用于拆分汽车零件的安装工作,并分配给各安装节点,最终实现汽车从零件到成品的量产。在报销审批流程中,责任链模式可以确保请假流程的合理性和效率。
- 复杂请求处理:责任链模式适用于需要处理复杂业务逻辑的场景,通过将请求的处理链式传递,可以有效地分解和组合处理步骤,提高系统的灵活性和可维护性。
责任链模式通过降低耦合度、提高系统的灵活性和可扩展性,适用于需要动态处理请求且处理逻辑可能发生变化的场景。然而,在使用责任链模式时需注意其潜在的性能问题和配置不当可能导致的错误处理。
4. 优缺点
- 优点:
- 降低耦合度:责任链模式允许请求的发送者和接收者之间保持松散耦合,减少了对象之间的直接依赖关系。
- 增强灵活性:可以通过动态地增加或删除处理者来改变请求的处理流程,从而提高系统的灵活性和可扩展性。
- 职责单一:每个处理者只负责自己感兴趣的请求,这使得每个处理者的职责更加明确,符合单一职责原则。
- 代码清晰:将复杂的逻辑分解到多个处理节点中,职责单一,使得代码结构更加清晰。
- 符合开闭原则:可以在不修改现有代码的情况下,通过添加新的处理者来扩展系统功能。
- 缺点:
- 性能问题:当责任链较长时,请求需要遍历整个链才能找到合适的处理者,这可能导致性能下降。
- 调试困难:由于请求在责任链中传递,调试时可能会遇到跟踪请求流向的困难,特别是在链条较长的情况下。
- 请求可能未被处理:如果责任链中的每个处理者都不能处理请求,那么请求可能会一直传递到链的末端而未被处理。
- 维护复杂性增加:责任链的动态修改可能增加系统的复杂度,需要额外的管理措施来确保链的有效性和合理性。
责任链模式在实际应用中可以显著提高系统的灵活性和可扩展性,但同时也需要注意其潜在的性能和调试问题。在设计时应合理控制责任链的长度,并确保责任链的正确配置以避免不必要的性能损失和调试困难。
5. 总结
设置一个链,涉资一个等级,如果输入的等级很高,就往后运行。