设计模式---责任链
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许你将请求沿着处理者链进行发送,直至其中一个处理者对其进行处理。这种模式可以解耦请求的发送者和接收者,增加或修改处理者时不需要改变客户端代码,提高了系统的灵活性和可维护性。
在Java中实现责任链模式,首先需要定义一个处理器接口,处理器需要持有对下一个处理器的引用。每个具体的处理器类实现这个接口,并在处理请求时,要么处理它,要么将请求转发给链中的下一个处理器。(链式调用)
1. 逻辑图

2. 简单逻辑
一个简单的责任链模式实现可能包括以下几个部分:
2.1 Handler 接口:定义一个处理请求的方法。
public interface Handler {
void setNext(Handler next);
void handleRequest(Request request);
}
2.2 具体处理器:实现 Handler 接口的具体类。
它们将处理请求或将请求传递给链中的下一个处理器。
public class ConcreteHandlerA implements Handler {
private Handler next;
@Override
public void setNext(Handler next) {
this.next = next;
}
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE_A) {
// 处理请求
System.out.println("Handled in A");
} else {
if (next != null) {
next.handleRequest(request);
}
}
}
}
2.3 客户端代码:构建责任链并发送请求。
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
handlerA.setNext(handlerB);
handlerA.handleRequest(new Request(RequestType.TYPE_B));
3. 相关案例
电商交易系统中处理订单状态变化,可以使用责任链模式来处理不同的订单状态。每个状态的处理都可以看作是责任链中的一个环节,这样可以灵活地添加、删除或调整处理器顺序,无需修改现有代码。
首先,定义一个订单状态请求的类 OrderRequest,它包含了订单的相关信息和当前状态:
package com.xiaokai.model;
/**
* Author:yang
* Date:2024-09-15 10:03
* Description:责任链中处理的具体请求对象
*/
public class OrderRequest {
private String orderId;
private String currentStatus;
public OrderRequest(String orderId, String currentStatus) {
this.orderId = orderId;
this.currentStatus = currentStatus;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getCurrentStatus() {
return currentStatus;
}
public void setCurrentStatus(String currentStatus) {
this.currentStatus = currentStatus;
}
}
然后,定义一个处理器接口 OrderHandler,它声明了处理订单状态的方法和设置下一个处理器的方法:
package com.xiaokai.handler;
import com.xiaokai.model.OrderRequest;
/**
* Author:yang
* Date:2024-09-15 10:01
* Description:订单处理器接口
*/
public interface OrderHandler {
OrderHandler setNext(OrderHandler handler);
void handleRequest(OrderRequest order);
}
接下来,实现具体的处理器,比如 PaymentHandler、ShippingHandler 和 DeliveryHandler:
package com.xiaokai.handler.impl;
import com.xiaokai.handler.OrderHandler;
import com.xiaokai.model.OrderRequest;
public class DeliveryHandler implements OrderHandler {
private OrderHandler nextHandler;
@Override
public OrderHandler setNext(OrderHandler handler) {
return this.nextHandler = handler;
}
@Override
public void handleRequest(OrderRequest request) {
if ("Shipped".equals(request.getCurrentStatus())) {
// 处理已发货状态,准备交付
System.out.println("Delivering order: " + request.getOrderId());
// 假设交付成功后,更新状态
request.setCurrentStatus("Delivered");
} else {
// 如果不是已发货状态,传递给下一个处理器
System.out.println("Delivery not required for order: " + request.getOrderId());
if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
}
package com.xiaokai.handler.impl;
import com.xiaokai.handler.OrderHandler;
import com.xiaokai.model.OrderRequest;
public class PaymentHandler implements OrderHandler {
private OrderHandler nextHandler;
@Override
public OrderHandler setNext(OrderHandler handler) {
return this.nextHandler = handler;
}
@Override
public void handleRequest(OrderRequest request) {
if ("Pending".equals(request.getCurrentStatus())) {
// 处理待支付状态
System.out.println("Processing payment for order: " + request.getOrderId());
// 假设支付成功后,更新状态
request.setCurrentStatus("Paid");
} else {
// 如果不是待支付状态,传递给下一个处理器
System.out.println("Payment not required for order: " + request.getOrderId());
if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
}
package com.xiaokai.handler.impl;
import com.xiaokai.handler.OrderHandler;
import com.xiaokai.model.OrderRequest;
public class ShippingHandler implements OrderHandler {
private OrderHandler nextHandler;
@Override
public void handleRequest(OrderRequest request) {
if ("Paid".equals(request.getCurrentStatus())) {
// 处理已支付状态,准备发货
System.out.println("Shipping order: " + request.getCurrentStatus());
// 假设发货成功后,更新状态
request.setCurrentStatus("Shipped");
} else {
// 如果不是已支付状态,传递给下一个处理器
System.out.println("Shipping not required for order: " + request.getOrderId());
if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
@Override
public OrderHandler setNext(OrderHandler handler) {
this.nextHandler = handler;
return this.nextHandler;
}
}
最后,构建责任链并处理订单:
public class Main {
public static void main(String[] args) {
// 创建处理器实例
OrderHandler paymentHandler = new PaymentHandler();
OrderHandler shippingHandler = new ShippingHandler();
OrderHandler deliveryHandler = new DeliveryHandler();
// 构建责任链
paymentHandler.setNext(shippingHandler);
shippingHandler.setNext(deliveryHandler);
// 创建订单请求
OrderRequest request = new OrderRequest("xiaokai", "Paid");
// 从链的开始处理请求
paymentHandler.handleRequest(request);
// 打印最终状态
System.out.println("Order final status: " + request.getCurrentStatus());
}
}
输出:
Payment not required for order: xiaokai
Shipping order: Paid
Order final status: Shipped
注:在学习过程中可能会遇到
-
责任链过长:如果责任链过长,可能会导致性能问题。解决方案是优化链条顺序,将最常用的处理器放在前面,或者将责任链拆分成多个子链。
-
处理器无法处理请求:当所有处理器都无法处理请求时,可能会导致请求被忽略。解决方案是在链的末尾添加一个默认处理器,处理无法被处理的请求。
4. 应用
责任链模式在实际开发中有很多应用,比如权限验证、日志处理、过滤器链等。
4.1 权限验证
用来检查用户是否具有执行某个操作的权限。例如,一个请求可能需要经过多个权限验证步骤,每个步骤都是责任链中的一个处理器。
chain:
interface AccessControlHandler {
void setNext(AccessControlHandler next);
boolean handleRequest(AccessRequest request);
}
class RoleBasedHandler implements AccessControlHandler {
private AccessControlHandler next;
@Override
public void setNext(AccessControlHandler next) {
this.next = next;
}
@Override
public boolean handleRequest(AccessRequest request) {
if (request.username.equals("admin")) {
System.out.println("Admin access granted for: " + request.action);
return true;
} else {
if (next != null) {
return next.handleRequest(request);
}
System.out.println("Role-based access denied for: " + request.action);
return false;
}
}
}
class PermissionBasedHandler implements AccessControlHandler {
private AccessControlHandler next;
@Override
public void setNext(AccessControlHandler next) {
this.next = next;
}
@Override
public boolean handleRequest(AccessRequest request) {
// 假设有一个方法 checkPermission 检查用户是否有权限执行操作
if (checkPermission(request.username, request.action)) {
System.out.println("Permission-based access granted for: " + request.action);
return true;
} else {
if (next != null) {
return next.handleRequest(request);
}
System.out.println("Permission-based access denied for: " + request.action);
return false;
}
}
private boolean checkPermission(String username, String action) {
// 这里应该有实际的权限检查逻辑
return true; // 假设总是有权限
}
}
4.2 日志处理
用来将日志信息传递给多个日志处理器,例如控制台日志、文件日志和数据库日志。
chain:
interface LogHandler {
void setNext(LogHandler next);
void log(LogRequest request);
}
class ConsoleLogHandler implements LogHandler {
private LogHandler next;
@Override
public void setNext(LogHandler next) {
this.next = next;
}
@Override
public void log(LogRequest request) {
System.out.println("Console: " + request.message);
if (next != null) {
next.log(request);
}
}
}
class FileLogHandler implements LogHandler {
private LogHandler next;
@Override
public void setNext(LogHandler next) {
this.next = next;
}
@Override
public void log(LogRequest request) {
// 将日志信息写入文件
System.out.println("File: " + request.message);
if (next != null) {
next.log(request);
}
}
}
class DatabaseLogHandler implements LogHandler {
private LogHandler next;
@Override
public void setNext(LogHandler next) {
this.next = next;
}
@Override
public void log(LogRequest request) {
// 将日志信息保存到数据库
System.out.println("Database: " + request.message);
if (next != null) {
next.log(request);
}
}
}
4.3 过滤器链
过滤器链用于在请求到达Servlet之前或响应发送给客户端之后执行一系列过滤任务,例如日志记录、安全控制、请求数据预处理等。
具体代码可以参考Java Web过滤器源码部分。
更多推荐



所有评论(0)