五种高频设计模式及其在 Spring 中的应用揭秘

ops/2025/1/31 15:15:56/

五种高频设计模式及其在 Spring 中的应用揭秘

1. 适配器模式(Adapter Pattern)

模式简介

适配器模式是一种结构型设计模式,通过将一个接口转换为客户端期望的另一个接口,使得原本不兼容的接口可以协同工作。它的核心作用在于兼容性适配,解决“老接口”和“新需求”的冲突。

模式结构
  • 目标接口:客户端期望使用的接口。
  • 适配器类:实现目标接口,并持有被适配者的引用,将被适配者的方法转换为目标接口的方法。
  • 被适配者:需要适配的类,其接口与目标接口不兼容。
使用场景
  • 将旧系统的接口适配到新系统中。
  • 为现有类提供新接口。
  • 统一多种接口,提供通用方法。
Java 示例代码

需求描述:将一种老式日志格式适配为新式格式。

java">// 目标接口:新日志格式
public interface NewLogger {void log(String message);
}// 被适配者:老式日志格式
public class OldLogger {public void writeLog(String msg) {System.out.println("Old Logger: " + msg);}
}// 适配器类:适配老式日志为新格式
public class LoggerAdapter implements NewLogger {private final OldLogger oldLogger;public LoggerAdapter(OldLogger oldLogger) {this.oldLogger = oldLogger;}@Overridepublic void log(String message) {oldLogger.writeLog(message);  // 调用老式日志的实现}
}
在 Spring 框架中的应用

Spring 的 HandlerAdapter 是适配器模式的经典实现,用于适配不同类型的控制器到统一的处理逻辑。例如:

  • SimpleControllerHandlerAdapter:适配实现了 Controller 接口的控制器。
  • RequestMappingHandlerAdapter:适配标注了 @RequestMapping 的控制器方法。

核心代码:

java">public interface HandlerAdapter {boolean supports(Object handler);  // 检查适配器是否支持某个处理器ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}

通过适配器,Spring 能够支持多种控制器类型,提升框架的灵活性和扩展性。


2. 装饰器模式(Decorator Pattern)

模式简介

装饰器模式通过为对象动态地添加职责,而不是通过继承来扩展功能。它允许我们按照需求组合功能,从而实现高效的功能扩展。

模式结构
  • 组件接口:定义核心功能。
  • 具体组件:核心功能的实现类。
  • 装饰器类:实现组件接口,并包含对核心组件的引用,用于动态扩展功能。
  • 具体装饰器:实现特定扩展功能。
使用场景
  • 动态为对象添加功能(如 I/O 流)。
  • 需要在不改变原始类的前提下扩展功能。
Java 示例代码

需求描述:在发送通知前后添加日志功能。

java">// 抽象组件
public interface Notifier {void send(String message);
}// 具体组件:基本通知实现
public class EmailNotifier implements Notifier {@Overridepublic void send(String message) {System.out.println("发送邮件通知: " + message);}
}// 装饰器基类
public abstract class NotifierDecorator implements Notifier {protected final Notifier notifier;public NotifierDecorator(Notifier notifier) {this.notifier = notifier;}
}// 具体装饰器:添加日志功能
public class LoggingNotifierDecorator extends NotifierDecorator {public LoggingNotifierDecorator(Notifier notifier) {super(notifier);}@Overridepublic void send(String message) {System.out.println("日志:开始发送通知...");notifier.send(message);  // 调用被装饰对象的方法System.out.println("日志:通知发送完毕!");}
}
在 Spring 框架中的应用

Spring 中的 BeanPostProcessorSpring Security 的过滤器链体现了装饰器模式:

  • BeanPostProcessor:在 Bean 初始化前后动态添加行为。

    示例代码:

    java">public class LoggingBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("初始化前日志:" + beanName);return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("初始化后日志:" + beanName);return bean;}
    }
    

3. 观察者模式(Observer Pattern)

模式简介

观察者模式定义了一种一对多的依赖关系,当被观察对象的状态发生变化时,所有观察者会自动收到通知。它是事件驱动模型的基础。

模式结构
  • 主题(Subject):被观察的对象,维护观察者列表。
  • 观察者(Observer):需要被通知的对象。
  • 具体主题和具体观察者:实现主题和观察者接口的类。
使用场景
  • GUI 事件监听。
  • 数据变化通知机制。
  • 发布/订阅系统。
Java 示例代码

需求描述:实现一个简单的事件通知机制。

java">// 主题接口
public interface Subject {void attach(Observer observer);void detach(Observer observer);void notifyObservers(String message);
}// 观察者接口
public interface Observer {void update(String message);
}// 具体主题
public class NewsPublisher implements Subject {private final List<Observer> observers = new ArrayList<>();@Overridepublic void attach(Observer observer) {observers.add(observer);}@Overridepublic void detach(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers(String message) {for (Observer observer : observers) {observer.update(message);}}
}// 具体观察者
public class Subscriber implements Observer {private final String name;public Subscriber(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + " 收到消息: " + message);}
}
在 Spring 框架中的应用

Spring 的事件驱动模型基于观察者模式:

  • ApplicationEvent:事件基类。
  • ApplicationListener:监听器接口。
  • ApplicationEventPublisher:事件发布器。

示例:

java">@Component
public class MyEventListener implements ApplicationListener<MyEvent> {@Overridepublic void onApplicationEvent(MyEvent event) {System.out.println("监听到事件: " + event.getMessage());}
}public class MyEvent extends ApplicationEvent {private final String message;public MyEvent(Object source, String message) {super(source);this.message = message;}public String getMessage() {return message;}
}

4. 构建者模式(Builder Pattern)

模式简介

构建者模式通过分步构建复杂对象,将对象创建过程与其表示分离,特别适用于构建复杂对象。

模式结构
  • 产品(Product):要构建的复杂对象。
  • 构建者(Builder):定义构建产品的方法。
  • 具体构建者(ConcreteBuilder):实现构建过程。
  • 指导者(Director):指导构建者构建产品。
Java 示例代码
java">// 产品类
public class Computer {private String cpu;private String gpu;public static class Builder {private String cpu;private String gpu;public Builder cpu(String cpu) {this.cpu = cpu;return this;}public Builder gpu(String gpu) {this.gpu = gpu;return this;}public Computer build() {Computer computer = new Computer();computer.cpu = this.cpu;computer.gpu = this.gpu;return computer;}}
}
在 Spring 框架中的应用

Spring 中的 BeanDefinitionBuilder 是构建者模式的典型应用,用于动态定义 Bean:

java">BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class);
builder.addPropertyValue("name", "Spring");
builder.addPropertyValue("version", "5.x");

5. 责任链模式(Chain of Responsibility Pattern)

模式结构
  • 处理者接口(Handler):定义处理请求的方法。
  • 具体处理者(ConcreteHandler):实现处理逻辑,并决定是否将请求传递给下一个处理者。
  • 责任链:由多个处理者组成,按照顺序处理请求。
使用场景
  • 当多个对象都有可能处理同一请求时,将这些对象连成一条链,按顺序处理请求。
  • 需要动态组合处理逻辑,但又不希望硬编码逻辑的顺序。
Java 示例代码

需求描述:一个日志处理系统,根据日志的级别分别由不同的处理者处理。

java">// 处理者接口
public abstract class LogHandler {protected LogHandler nextHandler;  // 下一个处理者public void setNextHandler(LogHandler nextHandler) {this.nextHandler = nextHandler;}public abstract void handle(String message, String level);
}// 具体处理者:Debug日志处理
public class DebugLogHandler extends LogHandler {@Overridepublic void handle(String message, String level) {if ("DEBUG".equalsIgnoreCase(level)) {System.out.println("DEBUG日志处理: " + message);} else if (nextHandler != null) {nextHandler.handle(message, level);}}
}// 具体处理者:Error日志处理
public class ErrorLogHandler extends LogHandler {@Overridepublic void handle(String message, String level) {if ("ERROR".equalsIgnoreCase(level)) {System.out.println("ERROR日志处理: " + message);} else if (nextHandler != null) {nextHandler.handle(message, level);}}
}// 测试
public class LogHandlerTest {public static void main(String[] args) {// 创建处理链LogHandler debugHandler = new DebugLogHandler();LogHandler errorHandler = new ErrorLogHandler();debugHandler.setNextHandler(errorHandler);// 测试责任链debugHandler.handle("系统调试信息", "DEBUG");debugHandler.handle("系统错误信息", "ERROR");debugHandler.handle("未知级别日志", "INFO");  // 无处理者}
}

输出结果:

DEBUG日志处理: 系统调试信息
ERROR日志处理: 系统错误信息
在 Spring 框架中的应用

Spring 中责任链模式的应用非常广泛,以下是两个经典场景:

  1. Spring Security 的过滤器链

    • 在 Spring Security 中,FilterChainProxy 管理着一系列的安全过滤器。每个过滤器完成特定的职责,例如认证、授权或日志记录。
    • 这些过滤器按顺序组成责任链,当请求进入时,依次通过这些过滤器进行处理,直到过滤器链末端。

    配置示例:

    <http><custom-filter position="FORM_LOGIN_FILTER" ref="myCustomFilter"/>
    </http>
    

    代码实现:

    java">public class MyCustomFilter extends GenericFilterBean {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 在此处处理请求逻辑System.out.println("自定义过滤器处理请求...");chain.doFilter(request, response);  // 传递给下一个过滤器}
    }
    
  2. Spring MVC 的拦截器链

    • Spring MVC 的 HandlerInterceptor 提供了一个类似责任链模式的机制,用于在请求处理的不同阶段添加逻辑,例如请求前的权限校验或请求后的日志记录。

    示例代码:

    java">public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("前置处理逻辑...");return true;  // 返回 false 则中断请求链}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("后置处理逻辑...");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("完成处理逻辑...");}
    }
    

    注册拦截器:

    java">@Configuration
    public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor());}
    }
    

总结

通过本文,我们详细解读了五种常见设计模式在 Spring 框架中的应用:

  1. 适配器模式:用于将不同接口适配到统一接口(如 Spring 的 HandlerAdapter)。
  2. 装饰器模式:动态扩展对象功能(如 BeanPostProcessor)。
  3. 观察者模式:实现事件驱动机制(如 ApplicationListener)。
  4. 构建者模式:构建复杂对象(如 BeanDefinitionBuilder)。
  5. 责任链模式:组织多步骤处理(如 Spring Security 的过滤器链、Spring MVC 的拦截器链)。

设计模式在 Spring 中无处不在,理解并灵活运用这些模式,能够帮助开发者更深入地理解框架设计思想,并提升代码质量和系统的可维护性。建议在实际开发中多多关注框架源码中的设计模式应用,实践中不断提升自己的设计能力。


http://www.ppmy.cn/ops/154509.html

相关文章

SpringCloudGateWay和Sentinel结合做黑白名单来源控制

假设我们的分布式项目&#xff0c;admin是8087&#xff0c;gateway是8088&#xff0c;consumer是8086 我们一般的思路是我们的请求必须经过我们的网关8088然后网关转发到我们的分布式项目&#xff0c;那我要是没有处理我们绕过网关直接访问项目8087和8086不也是可以&#xff1…

react native i18n插值:跨组件trans

想要实现动态插值以及插入元素&#xff0c;如下效果 这个找了蛮久的&#xff0c;官网的例子在我这无效&#xff0c;所以网上找了比较久&#xff0c;没能理解用法。最后是在 github issue 中看到别人的用法&#xff0c;自己理解下实现出来了&#xff0c;所以这里记录下。 例如…

【愚公系列】《循序渐进Vue.js 3.x前端开发实践》036-案例:实现支持搜索和筛选的用户列表

标题详情作者简介愚公搬代码头衔华为云特约编辑&#xff0c;华为云云享专家&#xff0c;华为开发者专家&#xff0c;华为产品云测专家&#xff0c;CSDN博客专家&#xff0c;CSDN商业化专家&#xff0c;阿里云专家博主&#xff0c;阿里云签约作者&#xff0c;腾讯云优秀博主&…

单片机基础模块学习——按键

一、按键原理图 当把跳线帽J5放在右侧&#xff0c;属于独立按键模式&#xff08;BTN模式&#xff09;&#xff0c;放在左侧为矩阵键盘模式&#xff08;KBD模式&#xff09; 整体结构是一端接地&#xff0c;一端接控制引脚 之前提到的都是使用了GPIO-准双向口的输出功能&#x…

力扣动态规划-15【算法学习day.109】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;建议灵神的题单和代码随想录&#xff09;和记录自己的学习过程&#xff0c;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关…

分享|通过Self-Instruct框架将语言模型与自生成指令对齐

结论 在大型 “指令调整” 语言模型依赖的人类编写指令数据存在数量、多样性和创造性局限&#xff0c; 从而阻碍模型通用性的背景下&#xff0c; Self - Instruct 框架&#xff0c; 通过 自动生成 并 筛选指令数据 微调预训练语言模型&#xff0c; 有效提升了其指令遵循能…

vue3和vue2的区别有哪些差异点

Vue3 vs Vue2 主要差异对比指南 官网 1. 核心架构差异 1.1 响应式系统 Vue2&#xff1a;使用 Object.defineProperty 实现响应式 // Vue2 响应式实现 Object.defineProperty(obj, key, {get() {// 依赖收集return value},set(newValue) {// 触发更新value newValue} })Vue3…

视频网站服务器为什么需要使用负载均衡?

随着视频网站等娱乐活动的逐渐增加&#xff0c;进行使用的用户数量也在不断上升&#xff0c;大量的用户会给视频网站行业带来一定的访问压力&#xff0c;需要处理大量的媒体资料&#xff0c;比如上传视频图片和数据保存发布等内容&#xff0c;会消耗大量的带宽资源&#xff0c;…