34 设计模式:职责链模式-行为型模式

115 阅读7分钟

行为型模式之:

  • 观察者模式(Observer) ✅ 重要程度:⭐️⭐️⭐️⭐️⭐️

  • 迭代器模式(Iterator) ✅ 重要程度:⭐️⭐️⭐️⭐️⭐️

  • 策略模式(Strategy) ✅ 重要程度:⭐️⭐️⭐️⭐️

  • 模板方法模式(Template Method) ✅ 重要程度:⭐️⭐️⭐️

  • 职责链模式(Chain of Responsibility) ✅ 重要程度:⭐️⭐️⭐️

  • 命令模式(Command)
    重要程度:⭐️⭐️⭐️⭐️

  • 解释器模式(Interpreter)
    重要程度:⭐️

  • 中介者模式(Mediator)
    重要程度:⭐️⭐️

  • 备忘录模式(Memento)
    重要程度:⭐️⭐️

  • 状态模式(State)
    重要程度:⭐️⭐️⭐️

  • 访问者模式(Visitor)
    重要程度:⭐️

1.什么是职责链模式?

责任链模式是一种行为设计模式,它允许多个对象共同处理请求,而无需显式指定接收请求的对象。每个处理器对象都包含对下一个处理器对象的引用,从而形成一个链。请求沿着链传递,直到有一个处理器对象能够处理它为止。

举一个实际生活中的例子来说明责任链模式:假设有一个公司的请假申请流程,申请人向直接主管提交请假申请,如果直接主管批准则流程结束,否则请求将被转发给部门经理,如果部门经理也无法批准,则再次转发给总经理。总经理有权利批准任何请求。在这个流程中,每个处理者都是责任链中的一环,他们依次处理请求,直到请求被批准为止。

image.png

在软件开发中,职责链模式常常用于处理请求的过滤、验证、授权等场景。比如,一个网络请求需要经过多个拦截器(处理器)处理,每个拦截器可以对请求进行一些预处理、验证或者修改,然后再将请求传递给下一个拦截器,直到请求被处理完成。

2.职责链模式的使用

// 请求对象
class Request {
    private String url;

    public Request(String url) {
        this.url = url;
    }

    public String getUrl() {
        return url;
    }
}

// 响应对象
class Response {
    private String result;

    public Response(String result) {
        this.result = result;
    }

    public String getResult() {
        return result;
    }
}

// 处理器接口
interface RequestHandler {
    Response handleRequest(Request request);
}

// 具体处理器:验证请求
class AuthenticationHandler implements RequestHandler {
    @Override
    public Response handleRequest(Request request) {
        // 模拟验证请求的处理
        System.out.println("AuthenticationHandler: Authenticating request...");
        return new Response("Authentication success");
    }
}

// 具体处理器:日志记录
class LoggingHandler implements RequestHandler {
    @Override
    public Response handleRequest(Request request) {
        // 模拟记录日志的处理
        System.out.println("LoggingHandler: Logging request...");
        return new Response("Logging success");
    }
}

// 具体处理器:发送请求
class RequestSender implements RequestHandler {
    @Override
    public Response handleRequest(Request request) {
        // 模拟发送请求的处理
        System.out.println("RequestSender: Sending request to URL: " + request.getUrl());
        return new Response("Request sent successfully");
    }
}

// 责任链类
class RequestHandlerChain {
    private RequestHandler head;

    public void addHandler(RequestHandler handler) {
        if (head == null) {
            head = handler;
            return;
        }
        RequestHandler current = head;
        while (current != null) {
            if (current instanceof ChainedRequestHandler) {
                current = ((ChainedRequestHandler) current).getNextHandler();
            } else {
                break;
            }
        }
        ((ChainedRequestHandler) current).setNextHandler(handler);
    }

    public Response processRequest(Request request) {
        return head.handleRequest(request);
    }
}

// 用于支持链式调用的处理器类
abstract class ChainedRequestHandler implements RequestHandler {
    private RequestHandler nextHandler;

    public ChainedRequestHandler(RequestHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public RequestHandler getNextHandler() {
        return nextHandler;
    }

    public void setNextHandler(RequestHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    @Override
    public Response handleRequest(Request request) {
        Response response = doHandleRequest(request);
        if (nextHandler != null) {
            response = nextHandler.handleRequest(request);
        }
        return response;
    }

    protected abstract Response doHandleRequest(Request request);
}

public class Main {
    public static void main(String[] args) {
        // 创建处理器对象
        RequestHandlerChain chain = new RequestHandlerChain();
        chain.addHandler(new AuthenticationHandler());
        chain.addHandler(new LoggingHandler());
        chain.addHandler(new RequestSender());

        // 创建请求对象
        Request request = new Request("http://example.com/api");

        // 处理请求
        Response response = chain.processRequest(request);
        System.out.println("Response: " + response.getResult());
    }
}

3.开源框架

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll() // 允许公共资源访问
                .anyRequest().authenticated() // 其他请求需要认证
                .and()
            .formLogin()
                .loginPage("/login") // 指定登录页面
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

    // 其他配置方法...
}

Spring Security 是 Spring 框架提供的一个安全性解决方案,其安全过滤器链(Filter Chain)是一个典型的职责链模式的应用。让我们简要地介绍一下 Spring Security 的安全过滤器链的实现方式:

  1. 在 Spring Security 中,安全过滤器链是由一系列的安全过滤器组成的,每个安全过滤器都负责处理特定的安全功能,例如认证、授权、会话管理等。
  2. 这些安全过滤器以过滤器链的形式被注册到 Spring 应用程序上下文中,并且按照一定的顺序依次执行。每个安全过滤器都有一个特定的职责,如果当前安全过滤器无法处理请求,则会将请求传递给下一个安全过滤器处理。
  3. Spring Security 的过滤器链是由 FilterChainProxy 类来管理和执行的。FilterChainProxy 类是 Spring Security 中的核心类之一,它负责调用安全过滤器链中的过滤器来处理请求。
  4. 在 Spring Security 的配置中,我们可以通过 HttpSecurity 配置器来定义安全过滤器链。通过 HttpSecurity 配置器,我们可以添加、删除或修改安全过滤器,以满足特定的安全需求。

4.什么情况下使用职责链模式呢?

不管是请假还是网络请求,我们可以发现整个流程都是递进的,符合常理的有先后顺序。才可以使用链模式。

  1. 请求需要被多个对象依次处理: 当一个请求需要被多个对象依次处理,并且处理器的顺序可能变化或者动态配置时,可以考虑使用职责链模式。
  2. 避免请求发送者和接收者之间的耦合: 职责链模式可以将请求发送者和接收者解耦,发送者不需要知道接收者的具体处理方式,只需要将请求发送到链中的第一个处理器,然后由链中的处理器自行决定是否处理或者将请求传递给下一个处理器。
  3. 处理器之间具有动态性和灵活性: 职责链模式可以灵活地增加、删除或者修改处理器,从而满足不同的业务需求,而不需要修改请求发送者的代码。
  4. 避免硬编码处理逻辑: 职责链模式可以将处理逻辑封装在不同的处理器中,使得处理逻辑可以被动态配置和组合,避免了硬编码处理逻辑的情况出现。

5.职责链有什么优缺点呢?

职责链模式的优点包括:

  1. 降低耦合度: 职责链模式将请求的发送者和接收者解耦,请求发送者不需要知道具体的处理者是谁,而处理者也不需要知道请求的发送者是谁,从而降低了对象之间的耦合度。
  2. 灵活性和可扩展性: 职责链模式允许动态地添加、移除或者修改处理器,可以根据实际需求灵活地调整处理链的结构,从而满足不同的业务需求。
  3. 责任分担: 职责链模式可以将请求分散到多个处理器中,每个处理器只需负责自己能够处理的部分,避免了单个处理器负责处理所有请求的情况,提高了系统的可维护性和扩展性。
  4. 单一职责原则: 每个处理器只需要关注自己负责处理的请求类型,符合单一职责原则,代码清晰、易于理解和维护。

职责链模式的缺点包括:

  1. 请求处理不确定性: 由于请求发送者不知道请求最终会被谁处理,因此可能会出现请求无法被处理的情况,或者请求被处理了多次的情况,需要在设计时进行严格的控制。
  2. 性能问题: 职责链模式会导致请求在链上依次传递,直到找到能够处理该请求的处理器为止,可能会影响系统的性能,特别是链过长或者请求处理时间过长的情况下。
  3. 可能引入额外复杂性: 如果处理链过长或者处理器之间的关系复杂,可能会导致代码的可读性和维护性降低,需要在设计时进行合理的抽象和分层,避免过度复杂化