Java责任链模式

Java责任链模式

本文介绍广泛使用的行为模式————责任链模式。

1. 概述

责任链模式有一个源头命令对象和一系列处理对象组成。链中每个处理对象负责处理特定类型命令,处理完成后交给下一个处理对象。
责任链模式一般用于:

  • 解耦命令发送者和接受者
  • 处理时选择处理策略

下面通过示例进行说明。

2. 示例

示例使用责任链处理认证请求。输入认证提供者在该场景下是命令,每个认证处理器是独立处理对象。
首先定义处理器抽象类:

public abstract class AuthenticationProcessor {

    // 责任链中下一个处理器对象
    public AuthenticationProcessor nextProcessor;
    
    public AuthenticationProcessor(AuthenticationProcessor nextProcessor) {
        this.nextProcessor = nextProcessor;
    }

    public abstract boolean isAuthorized(AuthenticationProvider authProvider);
}

后面需要实现具体的处理类。现在我们看命令提供者,该场景下就是认证请求,首先定义接口:

public interface AuthenticationProvider {

}

为了简单,我们假设有好几种类型认证请求:

// 用户名和密码
public class UsernamePasswordProvider implements AuthenticationProvider {

}

// 安全认证,用于sso
public class SamlAuthenticationProvider implements AuthenticationProvider {

}

// OAuth
public class OAuthTokenProvider implements AuthenticationProvider {

}

对于不同类型认证请求,有相应的处理器。

public class OAuthAuthenticationProcessor extends AuthenticationProcessor {

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

    @Override
    public boolean isAuthorized(AuthenticationProvider authProvider) {

        if (authProvider instanceof OAuthTokenProvider) {
            return Boolean.TRUE;
        } else if (nextProcessor != null) {
            return nextProcessor.isAuthorized(authProvider);
        } else {
            return Boolean.FALSE;
        }
    }

}
public class UsernamePasswordAuthenticationProcessor extends AuthenticationProcessor {

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

    @Override
    public boolean isAuthorized(AuthenticationProvider authProvider) {
        if (authProvider instanceof UsernamePasswordProvider) {
            return Boolean.TRUE;
        } else if (nextProcessor != null) {
            return nextProcessor.isAuthorized(authProvider);
        } else {
            return Boolean.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,不是期望类型,接着委托给下一个处理器OAuthProcessor,OAuthProcessor负责处理该类型请求,因此测试通过。第二个测试链中没有更多处理器,测试失败。

3. 责任链模式适用场景分析

实例责任链模式需要了解几条重要原则:

  • 每个处理器负责处理特定类型命令,我们实例中所有处理器都实现自己isAuthorized方法。
  • 每个处理器都有下一个处理器的引用,示例中UsernamePasswordProcessor 引用 OAuthProcessor。
  • 每个处理器负责委托下一个处理,避免丢弃命令。我们示例中如果输入请求是SamlProvider 类型实例,那么请求得不到处理认证失败。
  • 处理器不能形成递归循环:示例中责任链是UsernamePasswordProcessor -> OAuthProcessor,如果后面有增加UsernamePasswordProcessor 则造成UsernamePasswordProcessor-> OAuthProcessor -> UsernamePasswordProcessor递归循环。

Java中责任链模式应用很普遍。几乎每天我们都在使用,经典示例即Servlet Filters,使用多个过滤器处理HTTP请求,虽然这种场景是每个过滤器都处理请求。
让我们看看一段代码加深理解:

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);
    }
}

上面代码中FilterChain的doFilter方法是负责传递请求给下一个过滤器。

到目前为止我们已经看了责任链模式的用途,但其也有些不足:

  • 可能造成问题:如果一个处理器调用下一个处理器失败会造成命令丢弃;如果处理器调用错误处理器会造成链变成环。
  • 可能创建深度堆栈跟踪影响性能。
  • 多个处理器导致重复代码,增加维护成本。

4. 总结

本文介绍了责任链模式及其优缺点,通过处理认证请求场景进行示例说明。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值