什么是责任链模式
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它通过将请求沿着一条处理链传递,直到某个处理器处理该请求或链的末端被到达,从而避免请求的发送者和接收者之间的耦合。
关键要点
-
请求处理链:在责任链模式中,请求会沿着一条由多个处理器(Handler)组成的链传递,每个处理器都有机会处理请求。处理器可以选择处理请求、部分处理请求,或者将请求传递给下一个处理器。
-
解耦:请求的发送者和处理者解耦,发送者不需要知道具体哪个处理器会处理请求,这提高了系统的灵活性和可扩展性。
结构
责任链模式包含以下几个主要角色:
-
处理器(Handler):定义了处理请求的接口,并实现链中下一个处理器的引用。通常包含一个
handleRequest
方法来处理请求。 -
具体处理器(ConcreteHandler):处理器接口的实现类,负责实际处理请求。如果处理不了,它会将请求传递给链中的下一个处理器。
-
客户端(Client):发出请求的客户端,并将请求发送到链上的第一个处理器。
示例1
假设我们有一个系统,它处理不同级别的用户请求:普通用户请求、经理请求和总监请求。系统按责任链的方式处理这些请求,只有合适的处理器才能处理特定的请求。
代码实现
- 定义处理器接口:
// 处理器接口,定义处理请求的方法
public abstract class Handler {
protected Handler nextHandler;
// 设置链中的下一个处理器
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
// 处理请求的方法
public abstract void handleRequest(String request);
}
- 实现具体处理器:
// 具体处理器:处理普通用户请求
public class UserHandler extends Handler {
@Override
public void handleRequest(String request) {
if (request.equals("User Request")) {
System.out.println("UserHandler 处理请求: " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
// 具体处理器:处理经理请求
public class ManagerHandler extends Handler {
@Override
public void handleRequest(String request) {
if (request.equals("Manager Request")) {
System.out.println("ManagerHandler 处理请求: " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
// 具体处理器:处理总监请求
public class DirectorHandler extends Handler {
@Override
public void handleRequest(String request) {
if (request.equals("Director Request")) {
System.out.println("DirectorHandler 处理请求: " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
- 客户端代码:
public class ChainOfResponsibilityDemo {
public static void main(String[] args) {
// 创建处理链
Handler userHandler = new UserHandler();
Handler managerHandler = new ManagerHandler();
Handler directorHandler = new DirectorHandler();
userHandler.setNextHandler(managerHandler); // 设置链的下一个处理器
managerHandler.setNextHandler(directorHandler);
// 发送请求
userHandler.handleRequest("User Request"); // 由 UserHandler 处理
userHandler.handleRequest("Manager Request"); // 由 ManagerHandler 处理
userHandler.handleRequest("Director Request"); // 由 DirectorHandler 处理
userHandler.handleRequest("Unknown Request"); // 没有处理器能处理
}
}
输出结果:
UserHandler 处理请求: User Request
ManagerHandler 处理请求: Manager Request
DirectorHandler 处理请求: Director Request
解释
-
处理链:在这个示例中,
UserHandler
、ManagerHandler
和DirectorHandler
组成了一条处理链。每个处理器尝试处理请求,如果不能处理,就将请求传递给链中的下一个处理器。 -
处理请求:每个处理器只有在它能够处理的情况下才会处理请求,否则它会将请求传递给下一个处理器。
责任链模式的优点
-
解耦请求发送者和接收者:请求发送者不需要知道哪个处理器会处理请求,减少了耦合。
-
动态组合处理器:可以动态地改变处理链,增加或删除处理器,而不影响请求发送者。
责任链模式的缺点
-
链可能变得很长:如果处理链很长,可能会影响性能,特别是每个处理器都不处理请求时。
-
可能没有处理器处理请求:如果链的末端都没有处理请求的处理器,可能会导致请求未被处理。
责任链模式广泛应用于需要动态决定处理请求顺序的场景,如权限验证、日志记录、请求过滤等。
示例2:客服系统
场景:
假设你有一个在线客服系统,它负责处理用户的各种请求(如一般查询、技术支持、投诉等)。用户的请求根据内容不同会由不同级别的客服人员处理。如果一个客服无法处理该请求,他们会将请求传递给下一级别的客服。
角色对应:
- 处理器(Handler):不同级别的客服人员(如普通客服、技术支持、主管)。
- 请求:用户的服务请求。
示例代码
- 定义处理器接口:
// 处理器接口,定义处理请求的方法
public abstract class CustomerSupportHandler {
protected CustomerSupportHandler nextHandler;
// 设置链中的下一个处理器
public void setNextHandler(CustomerSupportHandler nextHandler) {
this.nextHandler = nextHandler;
}
// 处理请求的方法
public abstract void handleRequest(String request);
}
- 实现具体处理器:
// 具体处理器:普通客服
public class GeneralSupportHandler extends CustomerSupportHandler {
@Override
public void handleRequest(String request) {
if (request.equals("General Inquiry")) {
System.out.println("GeneralSupport 处理请求: " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
// 具体处理器:技术支持
public class TechnicalSupportHandler extends CustomerSupportHandler {
@Override
public void handleRequest(String request) {
if (request.equals("Technical Issue")) {
System.out.println("TechnicalSupport 处理请求: " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
// 具体处理器:投诉处理
public class ComplaintHandler extends CustomerSupportHandler {
@Override
public void handleRequest(String request) {
if (request.equals("Complaint")) {
System.out.println("ComplaintHandler 处理请求: " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
- 客户端代码:
public class CustomerSupportDemo {
public static void main(String[] args) {
// 创建处理链
CustomerSupportHandler generalSupport = new GeneralSupportHandler();
CustomerSupportHandler technicalSupport = new TechnicalSupportHandler();
CustomerSupportHandler complaintHandler = new ComplaintHandler();
generalSupport.setNextHandler(technicalSupport); // 设置链的下一个处理器
technicalSupport.setNextHandler(complaintHandler);
// 发送请求
generalSupport.handleRequest("General Inquiry"); // 由 GeneralSupport 处理
generalSupport.handleRequest("Technical Issue"); // 由 TechnicalSupport 处理
generalSupport.handleRequest("Complaint"); // 由 ComplaintHandler 处理
generalSupport.handleRequest("Unknown Request"); // 没有处理器能处理
}
}
输出结果:
GeneralSupport 处理请求: General Inquiry
TechnicalSupport 处理请求: Technical Issue
ComplaintHandler 处理请求: Complaint
解释
-
普通客服处理一般查询:如果用户请求是一般查询(如服务信息),
GeneralSupportHandler
会处理它。 -
技术支持处理技术问题:如果请求是技术问题,
GeneralSupportHandler
会将请求传递给TechnicalSupportHandler
处理。 -
投诉处理:如果请求是投诉,最终会由
ComplaintHandler
处理。 -
未处理的请求:如果请求类型不在这些处理器的处理范围内,最终请求不会被处理。
责任链模式的应用场景
-
权限验证:如用户访问某个系统功能时,首先检查权限,若权限不足则依次传递给更高级别的检查器。
-
请求过滤:如Web服务器接收到的请求需要经过多个过滤器(如安全过滤、日志记录、数据格式验证)才能最终处理。
-
任务审批流程:如企业内部的审批流程,审批请求由不同级别的管理者依次处理,直到最终被批准或拒绝。
这个例子显示了责任链模式如何在实际应用中灵活应对不同种类的请求,而无需请求发送者知道具体哪个处理器会处理它。通过这种方式,系统可以轻松地扩展或修改请求处理流程,而不需要改动客户端代码。