Java设计模式之责任链模式

定义

  • 相对官方解释:将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这
    些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止

  • 个人理解: 实际就是当我有些需求比如对字符串作敏感词过滤,如果当前字符串满足某个敏感词或者某个处理逻辑,就不再继续执行下去,否则继续执行下去。当然责任链的变种也特别常用,就是类似一个字符串的处理逻辑,满足了一也会继续走下去。如果不使用设计模式你可能就是写一堆的if else 每次需要添加新的逻辑也是需要改变代码,让代码整体可维护性不强,如果使用责任链模式后,我们每次调整执行算法只需要添加新的执行器即可,就像我们再使用SpringMVC添加过滤器一样,我们不需要改变其他任何代码,仅仅只需要实现HandlerInterceptor接口即可

实现

这里使用一种相对简单好理解的实现方法

IHandler

首先抽象出一个处理抽象接口,所有处理器都必须实现该处理器的处理方法

public interface IHandler {

    /**
     * 所有子类实现该处理方法
     * @return
     */
    boolean handle();
}

Handler

然后就是各种各样的处理器

public class HandlerA implements IHandler{


    @Override
    public boolean handle() {
        // 处理逻辑
        System.out.println("处理器A开始处理了");
        return false;
    }
}

public class HandlerB implements IHandler{


    @Override
    public boolean handle() {
        // 处理逻辑
        System.out.println("处理器B开始处理了");
        return true;
    }
}

public class HandlerC implements IHandler{


    @Override
    public boolean handle() {
        // 处理逻辑
        System.out.println("处理器C开始处理了");
        return false;
    }
}

这里我们故意让 HandlerB 处理成功,这样演示效果就是HandlerC 不会被执行。

HandlerChain

最后看看关键的 HandlerChain 实现

public class HandlerChain {
    private List<IHandler> handlers = new ArrayList<>();

    /**
     * 添加处理器
     * @param handler
     */
    public void addHandler(IHandler handler) {
        this.handlers.add(handler);

    }

    /**
     * 执行处理
     */
    public void handle() {
        for (IHandler handler : handlers) {
            boolean handled = handler.handle();
            if (handled) {
                break;
            }

        }

    }


}

用一个 handlers 存储所有的执行器,然后遍历循环执行,如果遇到执行成功的,则返回不在继续执行

测试

public class Test{

    public static void main(String[] args) {
        HandlerChain handlerChain = new HandlerChain();
        handlerChain.addHandler(new HandlerA());
        handlerChain.addHandler(new HandlerB());
        handlerChain.addHandler(new HandlerC());
        handlerChain.handle();
    }
}

Java设计模式之责任链模式_第1张图片

SpringMVC拦截器中的应用

我们来看看SpringMvC中拦截器的应用
在springboot中我们要定义自定义拦截器其实很简单

  1. 实现 HandlerInterceptor 接口
public class TestInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截客户端发送的请求");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("拦截发送给客户端的请求");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        System.out.println("这里总是被执行");
    }


}
  1. 注册拦截器,即实现 WebMvcConfigurer接口
@Configuration
public class WebConfig implements WebMvcConfigurer {

	@Bean
    public AuthenticationInterceptor authenticationInterceptor() {
        return new AuthenticationInterceptor();
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/wx/**", "/store/**", "/merchant/**", "/admin/**");
    }

}

我们来看看实际执行拦截器的代码。在 HandlerExecutionChain 这个类中
Java设计模式之责任链模式_第2张图片
可以看到也是用一个HandlerInterceptor[]数组去保存所有注册的拦截器,然后遍历调用的。由于这里是讲设计模式所以不对源码作过多研究,感兴趣的小伙伴可以自己去研究

总结

看懂责任链模式很简单,实际要运用到项目和生产中还是要有相应的变化,比如可能会在 IHandler中做一个通用适配器的方法,满足适配器方法才会执行,然后所有处理器都必须执行,大致伪代码是这样的

for (IHandler handler : handlers) {
            if (handler.adapter(s)) {
                handler.handle();
            }
          

        }

业务是千变万化的,要更具实际需求选用合适的设计模式加一变形,满足自己复杂的业务,像我实际用到责任链模式也是做了好多改动类似,上面加了适配器,然后就是下一个处理器依赖于上一个处理器的结果集,种种都需要我们灵活运用,其实责任链模式还用另外的用类似链表的方式实现,只是个人感觉可读性不算特别好,所以这里没有给出这种实现,感兴趣的小伙伴可以自行了解

你可能感兴趣的:(JAVA设计模式,设计模式,责任链模式)