责任链模式(Chain of Responsibility Pattern)
概念
责任链模式是一种行为型设计模式,它使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
责任链模式的核心思想是把请求的处理责任从一个对象转移到多个对象上。通过设置链式处理机制,多个对象可以动态参与请求处理,同时提高系统的可扩展性。
应用场景
-
多处理器处理请求:当一个请求可能被多个对象处理时,可以采用责任链模式将这些处理对象串联起来,沿着链条传递请求,直到找到合适的处理者。
-
避免复杂条件判断:如果在处理某些请求时,需要使用大量的条件语句(
if-else
或switch-case
),可以通过责任链模式将处理逻辑分散到不同的对象中,从而避免代码臃肿、难以维护。 -
日志过滤或权限控制:在日志记录或权限验证的场景中,不同的日志级别或权限控制可以使用责任链模式进行逐级处理。例如,日志系统可以根据不同的日志级别决定是否记录或输出日志信息。
-
审批流程:当一个请求需要经过多级审批时,责任链模式可以很好地实现逐级审批的机制。如果某一级不能处理,则传递给下一层。
注意点
-
请求必须能最终得到处理:责任链模式的链条中必须有一个对象能够处理请求,否则请求可能被丢失。
-
链条过长时可能影响性能:如果链条中包含的处理者对象很多,请求在链中传递的时间可能会较长,因此链的长度不宜过长。
-
容易出现不必要的调用:如果链条中的某些处理者不必要地调用了处理方法,可能会导致不必要的性能开销。
核心要素
-
Handler(处理者接口/抽象类):定义处理请求的接口,同时包含设置下一个处理者的方法。
-
ConcreteHandler(具体处理者):实现处理者接口的类,负责处理具体的请求,或者将请求传递给下一个处理者。
-
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 {@Overridepublic 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 {@Overridepublic 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 {@Overridepublic 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();// 设置责任链:经理 -> 总监 -> CEOmanager.setNextApprover(director);director.setNextApprover(ceo);// 提交请求System.out.println("Requesting approval for amount 500:");manager.approveRequest(500); // Manager handles this requestSystem.out.println("\nRequesting approval for amount 3000:");manager.approveRequest(3000); // Director handles this requestSystem.out.println("\nRequesting approval for amount 10000:");manager.approveRequest(10000); // CEO handles this request}
}
输出结果:
Requesting approval for amount 500:
Manager approved request of amount 500Requesting approval for amount 3000:
Director approved request of amount 3000Requesting approval for amount 10000:
CEO approved request of amount 10000
各种变形用法完整示例
-
动态责任链
在某些情况下,责任链的顺序可能并不是固定的。可以动态设置处理者链条,从而灵活地控制请求的传递顺序。
代码示例:动态责任链
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
-
双向责任链
有时请求可能需要在链条中向前或向后传递。在这种情况下,可以实现双向责任链。
代码示例:双向责任链
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 {@Overridepublic 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);} }
-
链式日志处理
在日志系统中,可以使用责任链模式实现日志的逐级过滤。例如,只输出大于某个级别的日志。
代码示例:链式日志处理
// 抽象日志处理者 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;}@Overrideprotected void write(String message) {System.out.println("Console Logger: " + message);} }class FileLogger extends Logger {public FileLogger(int level) {this.level = level;}@Overrideprotected 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.");} }
通过这些示例,可以灵活运用责任链模式,根据业务需求构建多种责任链。