JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

Java责任链设计模式

wys521 2024-12-02 18:29:31 精选教程 19 ℃ 0 评论

概述

维基百科将责任链定义为一种由“一个命令对象源和一系列处理对象”组成的设计模式。

链中的每个处理对象都负责特定类型的命令,处理完成后,它将命令转发给链中的下一个处理器。

责任链模式适用于:

  • 让命令发送器和接收器解耦
  • 在处理命令时选择处理策略

示例

我们将使用责任链来创建一个用于处理身份验证请求的链。

输入身份验证提供程序将是命令,每个身份验证处理器将是一个单独的处理器对象。

首先为处理器创建一个抽象基类:

public abstract class AuthenticationProcessor {

    public AuthenticationProcessor nextProcessor;
    
    // standard constructors

    public abstract boolean isAuthorized(AuthenticationProvider authProvider);
}

接下来,创建具体的处理器来扩展AuthenticationProcessor:

public class OAuthProcessor extends AuthenticationProcessor {

    public OAuthProcessor(AuthenticationProcessor nextProcessor) {
        super(nextProcessor);
    }

    @Override
    public boolean isAuthorized(AuthenticationProvider authProvider) {
        if (authProvider instanceof OAuthTokenProvider) {
            return true;
        } else if (nextProcessor != null) {
            return nextProcessor.isAuthorized(authProvider);
        }
        
        return false;
    }
}

public class UsernamePasswordProcessor extends AuthenticationProcessor {

    public UsernamePasswordProcessor(AuthenticationProcessor nextProcessor) {
        super(nextProcessor);
    }

    @Override
    public boolean isAuthorized(AuthenticationProvider authProvider) {
        if (authProvider instanceof UsernamePasswordProvider) {
            return true;
        } else if (nextProcessor != null) {
            return nextProcessor.isAuthorized(authProvider);
        }
    return false;
    }
}

为传入的授权请求创建了两个具体的处理器:UsernamePasswordProcessor和OAuthProcessor。每一个处理器都会重写isAuthorized方法。

创建几个测试用例:

public class ChainOfResponsibilityTest {

    private static AuthenticationProcessor getChainOfAuthProcessor() {
        AuthenticationProcessor oAuthProcessor = new OAuthProcessor(null);
        return new UsernamePasswordProcessor(oAuthProcessor);
    }

    @Test
    public void givenOAuthProvider_whenCheckingAuthorized_thenSuccess() {
        AuthenticationProcessor authProcessorChain = getChainOfAuthProcessor();
        assertTrue(authProcessorChain.isAuthorized(new OAuthTokenProvider()));
    }

    @Test
    public void givenSamlProvider_whenCheckingAuthorized_thenSuccess() {
        AuthenticationProcessor authProcessorChain = getChainOfAuthProcessor();
 
        assertFalse(authProcessorChain.isAuthorized(new SamlTokenProvider()));
    }
}

上面的示例创建了一个身份验证处理器链:UsernamePasswordProcessor->OAuthProcessor。

首先,UsernamePasswordProcessor检查身份验证提供程序是否是UsernamePasswordProvider的实例,UsernamePasswordProcessor不是预期的输入,而是委托给OAuthProcessor。最后,OAuthProcessor处理该命令。

实施原则

在实施责任链时,需要牢记以下几个重要原则:

  • 链中的每个处理器都有其处理命令的实现:在上面的例子中,所有处理器都实现了isAuthorized
  • 链中的每个处理器都应该引用下一个处理器:比如UsernamePasswordProcessor委托给OAuthProcessor
  • 每个处理器都负责委派给下一个处理器,因此要小心丢弃的命令:同样在示例中,如果命令是SamlProvider的实例,那么该请求可能不会得到处理,并且将是未经授权的
  • 处理器不应形成递归循环:在例子中,链中没有出现循环:UsernamePasswordProcessor->OAuthProcessor
  • 链中只有一个处理器处理给定的命令:在示例中,如果传入命令包含OAuthTokenProvider的实例,那么只有OAuthProcessor将处理该命令

Spring框架中的实际用例

Java中的Servlet过滤器就是这样一个经典的例子,它允许多个过滤器处理一个HTTP请求。每个过滤器需要调用FilterChain的doFilter方法,以便将请求传递给链中的下一个处理器。

public class CustomFilter implements Filter {

    public void doFilter(
      ServletRequest request,
      ServletResponse response,
      FilterChain chain)
      throws IOException, ServletException {

        // process the request

        // pass the request (i.e. the command) along the filter chain
        chain.doFilter(request, response);
    }
}

结论

责任链模式对于链式命令处理非常有用,不过也有一些缺点:

  • 如果某个处理器无法调用下一个处理器,则该命令将被丢弃
  • 如果处理器调用错误的处理器,可能会导致循环
  • 可能创建深度堆栈跟踪,从而影响性能

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表