设计模式——责任链模式(Chain of Responsibility Pattern)+ Spring相关源码

文章目录

  • 一、责任链模式定义
  • 二、例子
    • [2.1 菜鸟教程](#2.1 菜鸟教程)
      • [2.1.1 定义一个抽象日志类](#2.1.1 定义一个抽象日志类)
      • [2.1.2 定义日志类的具体实现类ConsoleLogger 、ErrorLogger 、FileLogger](#2.1.2 定义日志类的具体实现类ConsoleLogger 、ErrorLogger 、FileLogger)
      • [2.1.3 将日志类串起来,并使用](#2.1.3 将日志类串起来,并使用)
    • [2.2 JDK源码------Filter](#2.2 JDK源码——Filter)
    • [2.3 Spring源码------HandlerInterceptor](#2.3 Spring源码——HandlerInterceptor)
  • 三、其他设计模式

一、责任链模式定义

类型: 行为型模式

每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
目的: 职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

个人理解:上面菜鸟教程说职责链将发送者和请求的处理者解耦,但个人觉得职责链更多的是将多个责任解耦,使用时将所需要的责任组织成责任链。

二、例子

2.1 菜鸟教程

菜鸟教程是以一个日志类为例子。

2.1.1 定义一个抽象日志类

java 复制代码
public abstract class AbstractLogger {
   public static int INFO = 1;
   public static int DEBUG = 2;
   public static int ERROR = 3;
 
   protected int level;
 
   //责任链中的下一个元素
   protected AbstractLogger nextLogger;
 
   public void setNextLogger(AbstractLogger nextLogger){
      this.nextLogger = nextLogger;
   }
 
   public void logMessage(int level, String message){
      if(this.level <= level){
         write(message);
      }
      if(nextLogger !=null){
         nextLogger.logMessage(level, message);
      }
   }
 
   abstract protected void write(String message);
   
}

2.1.2 定义日志类的具体实现类ConsoleLogger 、ErrorLogger 、FileLogger

java 复制代码
public class ConsoleLogger extends AbstractLogger {
 
   public ConsoleLogger(int level){
      this.level = level;
   }
 
   @Override
   protected void write(String message) {    
      System.out.println("Standard Console::Logger: " + message);
   }
}
java 复制代码
public class ErrorLogger extends AbstractLogger {
 
   public ErrorLogger(int level){
      this.level = level;
   }
 
   @Override
   protected void write(String message) {    
      System.out.println("Error Console::Logger: " + message);
   }
}
java 复制代码
public class FileLogger extends AbstractLogger {
 
   public FileLogger(int level){
      this.level = level;
   }
 
   @Override
   protected void write(String message) {    
      System.out.println("File::Logger: " + message);
   }
}

2.1.3 将日志类串起来,并使用

java 复制代码
public class ChainPatternDemo {
   
   private static AbstractLogger getChainOfLoggers(){
 
      AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
      AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
      AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);
 
      errorLogger.setNextLogger(fileLogger);
      fileLogger.setNextLogger(consoleLogger);
 
      return errorLogger;  
   }
 
   public static void main(String[] args) {
      AbstractLogger loggerChain = getChainOfLoggers();
 
      loggerChain.logMessage(AbstractLogger.INFO, "This is an information.");
 
      loggerChain.logMessage(AbstractLogger.DEBUG, 
         "This is a debug level information.");
 
      loggerChain.logMessage(AbstractLogger.ERROR, 
         "This is an error information.");
   }
}

2.2 JDK源码------Filter

java 复制代码
public interface Filter {
    default void init(FilterConfig filterConfig) throws ServletException {
    }

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    default void destroy() {
    }
}

2.3 Spring源码------HandlerInterceptor

java 复制代码
public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}
java 复制代码
public class HandlerExecutionChain {

	@Nullable
	private HandlerInterceptor[] interceptors;

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

三、其他设计模式

创建型模式
结构型模式

行为型模式

相关推荐
a56299161928 分钟前
【springboot】Spring 官方抛弃了 Java 8!新idea如何创建java8项目
java·spring boot·spring
文心快码BaiduComate1 小时前
Comate内置模型已支持 MiniMax-M2.7!
设计模式·程序员·前端框架
console.log('npc')2 小时前
Cursor,Trae,Claude Code如何协作生产出一套前后台app?
前端·人工智能·react.js·设计模式·ai·langchain·ai编程
代码探秘者3 小时前
【大模型应用】4.分块之六大策略
java·数据结构·后端·python·spring
那我掉的头发算什么3 小时前
【博客系统】基于Spring全家桶的博客系统(下)
java·后端·spring·mybatis·开发
独自破碎E3 小时前
【面试真题拆解】Spring中的注解
数据库·spring·面试
不吃香菜学java3 小时前
苍穹外卖-新增菜品需求分析
java·spring boot·spring·tomcat·maven·ssm
计算机学姐5 小时前
基于SpringBoot的中药材店铺管理系统
java·vue.js·spring boot·后端·spring·tomcat·推荐算法
yinyan13146 小时前
一起学springAI系列一:使用多种聊天模型
java·人工智能·spring boot·后端·spring·springai
阿成学长_Cain6 小时前
Linux 命令:ldconfig —— 动态链接库管理命令
java·开发语言·spring