深入了解Java设计模式之职责链模式

 更新时间:2022年09月07日 16:51:53   作者:小小张自由—>张有博  
Java设计模式中有很多种类别,例如单例模式、装饰模式、观察者模式等。本文将为大家详细介绍其中的职责链模式,感兴趣的可以了解一下

定义

使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

解决的问题

请求和处理分开、实现解耦、提高系统的灵活性

可以动态的调整请求的链条,增加系统灵活性

核心要点

职责链模式每个执行者都包含了另一个执行者的引用。如果一个对象不能处理该请求,会把请求传递给下一个执行者。

客户端需要动态的调整,执行者的上下级。

Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。

类图

代码实现

抽象父类

/**
 * 处理请求的抽象类
 *
 * @author Promsing(张有博)
 * @version 1.0.0
 * @since 2022/9/7 - 9:29
 */
public abstract class Handler {

    //维持一个下一个执行者的引用
    protected Handler handler;
    
    protected void setHandler(Handler handler) {
        this.handler = handler;
    }

    //处理请求的抽象方法
    public abstract void  processRequest(int request);
}

执行者-三个

/**
 *  只处理数字1-10
 *
 * @author Promsing(张有博)
 * @version 1.0.0
 * @since 2022/9/7 - 9:31
 */
public class ConcreteHandlerA extends Handler{
    @Override
    public void processRequest(int request) {
        if (request>=0 && request<10 ){
            System.out.println("ConcreteHandlerA已经处理完毕了  "+request);
            return;
        }
        if (handler!=null){
            //下一位处理
            handler.processRequest(request);
        }
    }
}

/**
 * 只处理数字10-20
 *
 * @author Promsing(张有博)
 * @version 1.0.0
 * @since 2022/9/7 - 9:31
 */
public class ConcreteHandlerB extends Handler{
    @Override
    public void processRequest(int request) {
        if (request>=10 && request<20 ){
            System.out.println("ConcreteHandlerB已经处理完毕了  "+request);
            return;
        }
        if (handler!=null){
            //下一位处理
            handler.processRequest(request);
        }
    }
}

/**
 *只处理数字30+
 *
 * @author Promsing(张有博)
 * @version 1.0.0
 * @since 2022/9/7 - 9:31
 */
public class ConcreteHandlerC extends Handler{
    @Override
    public void processRequest(int request) {
        if (request>=30 ){
            System.out.println("ConcreteHandlerC已经处理完毕了  "+request);
            return;
        }
        if (handler!=null){
            //下一位处理
            handler.processRequest(request);
        }
    }
}

客户端

public class Main {

    public static void main(String[] args) {
        //创建执行者
        Handler h1=new ConcreteHandlerA();
        Handler h2=new ConcreteHandlerB();
        Handler h3=new ConcreteHandlerC();

        //设置向下级的顺序,可根据配置动态设置上下级
        h1.setHandler(h2);
        h2.setHandler(h3);
        int[] requests={8,11,23,50,7,19,28,40};

        //循环处理请求,不同的数值,交给不同的执行者
        for (int request : requests) {

            h1.processRequest(request);
        }
    }

}

拓展

SpringMVC中DispatchServlet使用职责链

 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;//请求
        HandlerExecutionChain mappedHandler = null;//执行链

        try {
            ModelAndView mv = null;
            Exception dispatchException = null;

            try {

                // Determine handler for the current request.
                mappedHandler = getHandler(processedRequest); //根据请求-获得执行链
                //判断mappedHandler是否为空,空:404
                if (mappedHandler == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }

                // 确定当前请求的处理程序适配器
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                //职责链的前置拦截
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                //执行handler方法-controller
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

                //职责链的后置拦截
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            //对结果集进行处理
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            //执行完成了拦截器
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
       
        finally {
            //资源释放 
        }
    }

拦截器的方法

	boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HandlerInterceptor[] interceptors = getInterceptors(); //获得拦截器
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = 0; i < interceptors.length; i++) {//循环遍历执行前置拦截
				HandlerInterceptor interceptor = interceptors[i];
				if (!interceptor.preHandle(request, response, this.handler)) {
					triggerAfterCompletion(request, response, null);
					return false;
				}
				this.interceptorIndex = i;
			}
		}
		return true;
	}


	void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
			throws Exception {

		HandlerInterceptor[] interceptors = getInterceptors(); //获得拦截器
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = interceptors.length - 1; i >= 0; i--) { //循环遍历执行后置拦截
				HandlerInterceptor interceptor = interceptors[i];
				interceptor.postHandle(request, response, this.handler, mv);
			}
		}
	
        
        
        	void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
			throws Exception {

		HandlerInterceptor[] interceptors = getInterceptors(); //获得拦截器
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = this.interceptorIndex; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				try {   //循环遍历执行完成拦截
					interceptor.afterCompletion(request, response, this.handler, ex);
				}
				catch (Throwable ex2) {
					logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
				}
			}
		}
	}

应用场景

1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。

2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。

3、可动态指定一组对象处理请求。

4、比如:JS 中的事件冒泡,JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。

到此这篇关于深入了解Java设计模式之职责链模式的文章就介绍到这了,更多相关Java职责链模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 如何利用Java使用AOP实现数据字典转换

    如何利用Java使用AOP实现数据字典转换

    这篇文章主要介绍了如何利用Java使用AOP实现数据字典转换,AOP也是我们常说的面向切面编程,AOP在我们开发过程中应用也比较多,在这里我们就基于AOP来实现一个数据字典转换的案例
    2022-06-06
  • Java AQS 线程安全同步队列的实现

    Java AQS 线程安全同步队列的实现

    AQS 同步队列是很多的 Java 线程安全对象的实现,例如 ReentrantLock, Semaphore, CountDownLatch, ReentrantReadWriteLock 等等,本文就介绍了Java AQS 线程安全同步队列的实现,感兴趣的可以了解一下
    2023-08-08
  • 深入Spring Boot实现对Fat Jar jsp的支持

    深入Spring Boot实现对Fat Jar jsp的支持

    这篇文章主要介绍了深入Spring Boot实现对Fat Jar jsp的支持,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • 如何获取java类中的属性注释

    如何获取java类中的属性注释

    在开发中,有时需要获取Java类的属性注释,尤其是当JPA生成的表缺少注释时,可以通过jdk自带的tools.jar工具包来实现,方法类似于生成javadoc文档,需要在pom.xml文件中导入tools.jar的依赖,该jar文件一般位于JAVA_HOME/lib目录下
    2024-09-09
  • Java数据结构之线性表

    Java数据结构之线性表

    线性表是其组成元素间具有线性关系的一种数据结构,对线性表的基本操作主要有,获取元素,设置元素值,遍历,插入,删除,查找,替换,排序等。而线性表可以采用顺序储存结构和链式储存结构,本节主要讲解顺序表、单链表以及双链表的各种基本操作。
    2017-03-03
  • Java生成10个1000以内的随机数并用消息框显示数组内容然后求和输出

    Java生成10个1000以内的随机数并用消息框显示数组内容然后求和输出

    这篇文章主要介绍了Java生成10个1000以内的随机数并用消息框显示数组内容然后求和输出,需要的朋友可以参考下
    2015-10-10
  • MybatisPlus+Postgresql整合的几个坑及解决

    MybatisPlus+Postgresql整合的几个坑及解决

    这篇文章主要介绍了MybatisPlus+Postgresql整合的几个坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • java实现扫雷小游戏

    java实现扫雷小游戏

    这篇文章主要为大家详细介绍了java实现扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-01-01
  • Java实现简单学生管理系统

    Java实现简单学生管理系统

    这篇文章主要为大家详细介绍了Java实现简单学生管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • Hibernate validator使用以及自定义校验器注解

    Hibernate validator使用以及自定义校验器注解

    这篇文章主要介绍了Hibernate validator使用以及自定义校验器注解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01

最新评论