责任链模式(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过滤器源码部分。        

更多推荐