设计模式的分类及Spring中用到的设计模式

设计模式的分类

在《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software)一书中,提出了 23 种设计模式,通常称为 GoF(Gang of Four)设计模式。这些设计模式被分为以下三种类型:

  1. 创建型模式(Creational Patterns):

    • 工厂方法模式(Factory Method Pattern)

    • 抽象工厂模式(Abstract Factory Pattern)

    • 单例模式(Singleton Pattern)

    • 建造者模式(Builder Pattern)

    • 原型模式(Prototype Pattern)

  2. 结构型模式(Structural Patterns):

    • 适配器模式(Adapter Pattern)

    • 桥接模式(Bridge Pattern)

    • 组合模式(Composite Pattern)

    • 装饰者模式(Decorator Pattern)

    • 外观模式(Facade Pattern)

    • 享元模式(Flyweight Pattern)

    • 代理模式(Proxy Pattern)

  3. 行为型模式(Behavioral Patterns):

    • 责任链模式(Chain of Responsibility Pattern)

    • 命令模式(Command Pattern)

    • 解释器模式(Interpreter Pattern)

    • 迭代器模式(Iterator Pattern)

    • 中介者模式(Mediator Pattern)

    • 备忘录模式(Memento Pattern)

    • 观察者模式(Observer Pattern)

    • 状态模式(State Pattern)

    • 策略模式(Strategy Pattern)

    • 模板方法模式(Template Method Pattern)

    • 访问者模式(Visitor Pattern)

这三种类型的设计模式分别涵盖了对象的创建、结构和行为方面的需求,每种类型的设计模式在特定的场景下都能提供有效的解决方案,从而帮助开发人员构建更加可复用、灵活和可维护的面向对象软件系统。

Spring 框架用到的设计模式

创建型模式(Creational Patterns):

工厂方法模式(Factory Method Pattern)

另一个在 Spring 框架中应用的设计模式思想是工厂模式,具体体现在 Spring 的 Bean 工厂中。Spring 使用工厂模式来创建和管理 Bean 实例,其中最常见的是使用 ApplicationContext 或 BeanFactory 这样的工厂来创建和配置 Bean 对象。这种工厂模式隐藏了对象的创建细节,使得应用程序的代码不需要直接依赖具体类的实例化过程,从而实现松耦合和更好的可维护性。

通过 ApplicationContext 或 BeanFactory,Spring 的应用程序可以通过配置文件、注解或 Java 代码来描述 Bean 对象的创建和依赖关系,而不需要直接使用 new 关键字来实例化对象。这使得系统更加灵活,能够更方便地进行扩展和修改,符合开闭原则。

  • 抽象工厂模式(Abstract Factory Pattern)

    单例模式(Singleton Pattern)

    Spring 框架中,单例模式被广泛应用于管理 Bean 实例,以确保在整个应用程序范围内只存在一个实例。这样做有助于节省资源,提高性能,并且在某些情况下也能确保状态的一致性。

    Spring 使用了一种叫做"容器单例"的方式来管理 Bean 的实例。容器单例是指在 Spring 容器中管理的单例对象,在整个容器生命周期中只存在一个实例。这一思想借鉴了单例模式的设计理念,但并不是严格意义上的传统单例模式。在传统单例模式中,类的构造方法是私有的,通过静态方法获取实例,而 Spring 中的容器单例则是统一由 Spring 容器进行管理和维护的。

    在 Spring 中,容器单例确保了应用程序中对同一个 Bean 的多次请求都返回同一个实例,这有利于避免重复创建对象,节省资源。此外,容器单例也符合 Spring 框架对 Bean 生命周期的管理,例如在初始化和销毁阶段发挥了作用。

    总的来说,Spring 框架中的单例模式思想体现在对 Bean 实例的管理上,通过容器单例的方式确保了在应用程序中某个 Bean 只存在一个实例,从而提高了系统的性能和资源利用率。

    建造者模式(Builder Pattern)

    是的,建造者模式在 Spring 框架中也有应用。虽然建造者模式不像适配器模式、代理模式等那么显而易见,但在某些场景下,Spring 框架中的一些组件和功能确实体现了建造者模式的思想。

    一个经典的例子是 Spring 中的 BeanDefinitionBuilder 类。在 Spring 中,我们可以通过 BeanDefinitionBuilder 来构建并定义 Bean 的属性、依赖关系等配置信息,然后通过 BeanDefinitionReader 将其注册到 Spring 容器中。BeanDefinitionBuilder 的设计与建造者模式相似,它通过使用链式调用的方式来设置 Bean 的属性,最终创建一个符合需求的 BeanDefinition 对象,实现了更加灵活且易于理解的 Bean 定义方式。

    另外,Spring 中的 JdbcTemplate 也可以看作是建造者模式的应用。通过 JdbcTemplate,开发者可以通过链式调用的方式来构建 SQL 查询语句、设置参数等,最终执行数据库操作。这种使用方式类似于建造者模式,让开发者可以按照自己的需求来构建和执行数据库操作,提高了代码的可读性和可维护性。

    总的来说,虽然建造者模式在 Spring 框架中可能没有明显的固定实现,但在一些组件和功能的设计中,我们可以看到建造者模式的思想被巧妙地应用,从而提高了代码的灵活性和可维护性。建造者模式的使用有助于简化对象的创建过程,将复杂对象的构建与表示分离,使得代码更加清晰和易于扩展。

    原型模式(Prototype Pattern)
  • 在 Spring 框架中,虽然没有直接使用原型模式(Prototype Pattern),但是可以从一些功能和特性中识别出与原型模式相关的设计思想。下面是一些 Spring 中应用了与原型模式类似的设计思想:

    1. 原型Bean(Prototype Bean): Spring 容器中的 Bean 可以被声明为原型作用域(prototype scope)。当一个 Bean 被声明为原型作用域时,每次注入或者获取该 Bean 时,容器都会创建一个新的实例。这类似于原型模式中创建新对象实例的概念。

    2. Bean 的克隆: 在 Spring 中,Bean 可以通过特定的方式来克隆,例如使用 Object 类的 clone() 方法,或者在配置文件中通过配置原型 Bean 来获取 Bean 的一个新实例。这种方式类似于原型模式中通过克隆来创建新对象的过程。

    3. 原型注册表(Prototype Registry): 在 Spring 中,可以通过原型注册表的方式来管理原型 Bean 的创建和获取。原型注册表类似于原型模式中的原型管理器,负责管理原型对象的创建和复制。

    尽管 Spring 框架没有直接使用原型模式来实现其功能,但是通过原型作用域的 Bean、Bean 的克隆和原型注册表等特性,可以看出 Spring 框架中采用了与原型模式类似的设计思想。这种设计思想使得 Spring 容器能够有效地管理原型 Bean 的创建和使用,同时为开发者提供了更灵活的对象创建和管理方式。

结构型模式(Structural Patterns):

适配器模式(Adapter Pattern)

在 Spring 框架中,适配器模式(Adapter Pattern)被广泛应用于各个模块和功能。以下是一些 Spring 中使用适配器模式的常见示例:

  1. MVC 框架中的适配器: 在 Spring 的 MVC(Model-View-Controller)框架中,适配器模式用于连接控制器(Controller)和处理器(Handler)。Spring 提供了适配器类(如 HttpRequestHandlerAdapterSimpleControllerHandlerAdapter)来处理不同类型的控制器(如实现 HttpRequestHandler 接口的处理器、继承 AbstractController 的处理器等),并将请求适配到对应的处理器上。

  2. AOP 框架中的适配器: 在 Spring 的 AOP(面向切面编程)框架中,适配器模式用于连接切面(Aspect)和切点(Pointcut)。Spring 提供了适配器类(如 MethodBeforeAdviceAdapterAfterReturningAdviceAdapter)来将切面适配到特定类型的切点上,从而在切点的前后执行相应的通知。

  3. 事务管理中的适配器: Spring 的事务管理模块借助适配器模式来实现不同事务管理器之间的适配。Spring 提供了多个事务管理器适配器类(如 DataSourceTransactionManagerJtaTransactionManager),将不同的事务管理器(如 JDBC 事务、JTA 事务)适配成 Spring 框架能够识别和使用的统一方式。

  4. 消息处理中的适配器: 在 Spring 的消息处理模块中,适配器模式用于连接消息发送者和接收者。Spring 提供了适配器类(如 MessageListenerAdapterJmsListenerEndpointAdapter),将不同类型的消息发送者适配到统一的消息接收器上,使得消息的发送和接收可以进行适配和协同工作。

总之,适配器模式在 Spring 框架中被广泛使用,用于连接和适配不同组件、接口和机制。通过适配器模式,Spring 实现了多个模块之间的解耦,提供了统一、灵活和可扩展的框架结构。

桥接模式(Bridge Pattern)

在 Spring 框架中,桥接模式经常被用于实现依赖注入(Dependency Injection,DI)和面向接口编程。

Spring 框架通过桥接模式将组件的实现与其依赖关系解耦,提供了一种灵活的方式来管理组件之间的关系。以下是桥接模式在 Spring 中的一些应用场景:

  1. 依赖注入(Dependency Injection,DI):Spring 使用桥接模式通过依赖注入的方式来解耦组件之间的依赖关系。通过将依赖关系定义在组件的接口或抽象类中,并将其与具体的实现进行桥接,Spring 可以在运行时动态地将适当的实现注入到组件中。

  2. JDBC 桥接:Spring 的 JDBC 模块提供了一个 JDBC 桥接,它允许开发人员使用 Spring 的 JdbcTemplate 来操作数据库,而不必关心底层的 JDBC API。这个桥接模式隐藏了底层的 JDBC 细节,并提供了更简洁、更易用的 API。

  3. AOP(面向切面编程)桥接:Spring 的 AOP 模块使用了桥接模式来提供面向切面编程的功能。通过定义切面(Aspect)和通知(Advice),并将它们桥接到目标对象上,Spring 能够实现横切关注点的模块化和重用。

  4. 模板方法模式桥接:Spring 的 JdbcTemplate 和 HibernateTemplate 等模板类使用了桥接模式。这些模板类将数据库操作的细节封装起来,并提供统一的模板方法供开发人员使用。通过桥接的设计,模板类能够适配不同的数据访问技术(如 JDBC、Hibernate)。

总的来说,桥接模式在 Spring 框架中广泛应用于解耦组件之间的关系,提供了强大的灵活性和可扩展性。它帮助开发人员实现面向接口编程,并通过依赖注入、AOP、模板方法等技术来管理组件之间的依赖关系,提高了系统的可测试性、可维护性和可扩展性。

组合模式(Composite Pattern)
装饰者模式(Decorator Pattern)

在 Spring 框架中,装饰器模式的应用并不是特别明显,因为 Spring 更多地使用了代理模式来实现 AOP(面向切面编程)和事务管理等功能。然而,Spring 框架中也存在一些类似装饰器模式的特性,用于给对象动态地添加功能或修改行为。

  1. BeanPostProcessor : Spring 框架中的 BeanPostProcessor 接口就类似于装饰者模式,在对象初始化的时候可以对对象进行增强处理。具体来说,BeanPostProcessor 接口中有两个方法 postProcessBeforeInitializationpostProcessAfterInitialization,这两个方法允许开发者在初始化 bean 之前和之后对其进行一些自定义操作,比如包装成代理对象,修改属性等。

  2. AOP装饰器: 在 Spring 框架中,AOP(面向切面编程)可以使用代理模式来实现,但在某种程度上也展现了装饰器模式的特征。在 AOP 中,可以通过切面(Aspect)给原始的对象动态地添加功能,比如日志记录、事务管理等。虽然是代理模式在工作,但从功能扩展的角度来看,也具有一定的装饰者模式的特点。

虽然 Spring 框架中使用的装饰者模式并不明显,但可以看到一些类似装饰者模式的特性被应用在 Spring 的不同组件中,从而提供了灵活地对对象进行增强和修改行为的能力。

外观模式(Facade Pattern)
享元模式(Flyweight Pattern)

代理模式(Proxy Pattern)

在 Spring 框架中还有一个经典的设计模式是代理模式。代理模式在 Spring 中被广泛应用于 AOP(面向切面编程)和事务管理等方面。

在 AOP 中,Spring 使用了动态代理来实现横切关注点(如日志记录、性能监控、事务管理等)的功能。通过代理模式,Spring 创建了代理对象来包装原始对象,并在代理对象中插入横切逻辑,使得这些逻辑能够与原始对象的业务逻辑分离,从而实现了更好的模块化和可维护性。

在 Spring 的事务管理中,代理模式同样扮演了重要的角色。Spring 的事务管理通过 AOP 实现,允许开发者通过事务代理对象来管理事务的开始、提交、回滚等操作。这种方式下,代理模式帮助开发者将事务管理逻辑与业务逻辑分离,减少了业务代码中和事务处理相关的重复性代码,提高了代码的可读性和可维护性。

此外,在 Spring 的 IoC(控制反转)容器中,Bean 对象的实例化和生命周期管理也经常通过代理模式来完成。Spring 通过代理模式在 Bean 的实例化、初始化、销毁等过程中插入相应的逻辑,实现了对 Bean 生命周期的管理和控制。

总的来说,代理模式在 Spring 框架中发挥着重要的作用,帮助实现了 AOP、事务管理和 IoC 容器等功能。代理模式的运用使得 Spring 框架在面向对象设计中更加灵活、可扩展和易于维护。

行为型模式(Behavioral Patterns)

模板模式

还有一个在 Spring 框架中常见的设计模式是模板方法模式。这种模式在 Spring 的事务管理中得到了广泛的应用。

在 Spring 中,事务管理是通过 AOP 的方式实现的。Spring 提供了一种名为 TransactionTemplate 的模板类,该类封装了事务的创建、提交、回滚等操作,并提供了一个回调方法的机制,用户可以在回调方法中定义自己的业务逻辑。

使用 TransactionTemplate,开发者可以通过扩展并重写其中的回调方法,实现自己的业务逻辑,并在事务的开始和结束时自动执行相应的操作。这种方式下,事务处理的开始和结束的细节由框架控制,而业务逻辑的实现由开发者来定义,实现了框架与业务逻辑的解耦。

TransactionTemplate 的设计符合模板方法模式的思想,在模板方法模式中,定义一个抽象的父类,其中包含一个模板方法和若干个具体的子类实现。模板方法封装了通用的算法结构,而具体的实现由子类来完成,从而实现了代码的复用和扩展。

总结一下,在 Spring 框架中使用模板方法模式的案例是事务管理。通过 TransactionTemplate,开发者可以在事务的模板方法中定义自己的业务逻辑,而框架负责管理事务的创建和提交等细节,实现了代码的解耦和提高了开发效率。

观察者模式

在 Spring 框架中,观察者模式的概念被广泛应用于事件驱动的编程模型。Spring 提供了丰富的事件支持机制,可以在应用程序中实现可观察者和观察者之间的解耦合,从而实现事件的发布和订阅。

Spring 中观察者模式的应用主要体现在以下几个方面:

  1. 应用事件 :Spring 框架中有一个事件体系,通过 ApplicationEvent 及其子类表示事件对象。开发者可以在自己的应用程序中定义各种事件,比如用户注册事件、订单支付事件等。这些事件就充当着可观察者,可以被其他组件订阅。

  2. 事件发布者 :在 Spring 中,通过 ApplicationEventPublisher 接口或者使用 ApplicationEventPublisherAware 接口实现类,可以向应用程序中发布事件,充当着事件的发布者。

  3. 事件监听器 :通过实现 ApplicationListener 接口或者使用 @EventListener 注解,可以创建事件监听器,充当观察者。监听器可以订阅感兴趣的事件,并在事件发生时执行相应的逻辑。

下面是一个简单的示例,展示了 Spring 中观察者模式的应用:

首先,定义一个自定义事件类 MyCustomEvent

复制代码
import org.springframework.context.ApplicationEvent;
​
public class MyCustomEvent extends ApplicationEvent {
    private String message;
​
    public MyCustomEvent(Object source, String message) {
        super(source);
        this.message = message;
    }
​
    public String getMessage() {
        return message;
    }
}

然后,创建一个事件发布者 MyEventPublisher

复制代码
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
​
public class MyEventPublisher implements ApplicationEventPublisherAware {
    private ApplicationEventPublisher eventPublisher;
​
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }
​
    public void publishCustomEvent(String message) {
        eventPublisher.publishEvent(new MyCustomEvent(this, message));
    }
}

接下来,定义一个事件监听器 MyEventListener

复制代码
import org.springframework.context.ApplicationListener;
​
public class MyEventListener implements ApplicationListener<MyCustomEvent> {
    @Override
    public void onApplicationEvent(MyCustomEvent event) {
        System.out.println("Received custom event - " + event.getMessage());
    }
}

最后,在 Spring 配置文件中进行相关配置:

复制代码
<bean id="myEventPublisher" class="com.example.MyEventPublisher" />
<bean id="myEventListener" class="com.example.MyEventListener" />

在这个示例中,MyEventPublisher 充当事件的发布者,调用 publishCustomEvent 方法发布自定义事件;MyEventListener 充当事件监听器,通过实现 ApplicationListener 接口来订阅自定义事件,并在事件发生时执行相应的逻辑。通过这种方式,实现了可观察者和观察者之间的解耦合,符合观察者模式的设计思想。

总之,Spring 框架中的事件机制提供了一种高效的观察者模式的实现,可以让应用程序中的各个组件之间实现解耦合,更好地处理事件驱动的编程模型。

责任链模式

在 Spring 框架中,责任链模式通常用于实现拦截器和过滤器链,以及事件处理器链,充分发挥了责任链模式的灵活性和可扩展性。以下是 Spring 框架中责任链模式的一些应用场景:

  1. 拦截器链:Spring MVC 中的拦截器链就是典型的责任链模式。拦截器按照配置的顺序依次执行,每个拦截器都有机会在请求处理前或处理后执行相应的逻辑。如果某个拦截器决定拦截了请求,后续的拦截器将不再执行,类似于责任链模式中的处理者链。

  2. 过滤器链:在 Spring Security 中,过滤器链用于处理安全相关的操作。每个过滤器都有机会对请求进行安全处理,如果某个过滤器处理了请求,后续的过滤器就不再执行。

  3. 事件处理器链 :Spring 框架中的事件驱动模型也可以使用责任链模式。通过 ApplicationEventApplicationListener,开发者可以定义多个事件处理器,每个事件处理器可以根据自己的逻辑来处理事件,如果其中某个事件处理器处理了事件,后续的处理器将不再执行。

在这些场景中,Spring 框架充分利用责任链模式的特点,实现了灵活的请求处理和事件处理机制。责任链模式使得每个处理器能够独立地处理请求或事件,并根据自己的逻辑来决定是否传递给下一个处理器,从而实现了更好的模块化和扩展性。通过配置管理和依赖注入,Spring 框架提供了便利的方式来构建和管理责任链,使其成为实际项目中常用的设计模式之一。

策略模式

在 Spring 框架中,策略模式通常用于实现不同的业务逻辑之间的选择和切换。Spring 提供了多种方式来应用策略模式,以下是一些典型的应用场景:

  1. Bean 的选择策略 : 在 Spring IoC 容器中,可以使用策略模式来选择需要实例化的 bean。通过实现接口或者注解的方式,定义多个备选的具体 bean,并使用策略模式来选择合适的实例。例如,使用 @Conditional 注解可以根据条件选择不同的 bean 实例。

  2. AOP 中的切面选择策略: Spring AOP 提供了一种方便的方式来通过切面来处理横切关注点。在实际应用中,可以使用策略模式来选择不同的切面实现,根据具体的业务需求动态地切换切面的行为。

  3. 处理器选择策略: 在 Spring MVC 中,可以使用策略模式来选择不同的处理器(Controller)来处理请求。通过配置和路由规则,根据请求的特征选择不同的处理器来处理请求,实现灵活的请求处理策略。

  4. 缓存策略选择 : 在 Spring 中,可以使用策略模式来选择不同的缓存策略。通过实现 CacheManager 接口和自定义的缓存策略类,可以灵活地选择使用哪种缓存策略,以提高系统性能。

在这些场景中,Spring 框架应用了策略模式来实现不同算法或者策略的选择和切换。通过使用灵活的配置和扩展机制,Spring 框架提供了便利的方式来切换不同的策略实现,以满足不同的业务需求。策略模式帮助提高系统的可扩展性和灵活性,同时降低了各个模块之间的耦合度。

相关推荐
小白不太白9503 分钟前
设计模式之 模板方法模式
java·设计模式·模板方法模式
Tech Synapse5 分钟前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
.生产的驴6 分钟前
SpringCloud OpenFeign用户转发在请求头中添加用户信息 微服务内部调用
spring boot·后端·spring·spring cloud·微服务·架构
xoxo-Rachel12 分钟前
(超级详细!!!)解决“com.mysql.jdbc.Driver is deprecated”警告:详解与优化
java·数据库·mysql
乌啼霜满天24914 分钟前
JDBC编程---Java
java·开发语言·sql
色空大师26 分钟前
23种设计模式
java·开发语言·设计模式
闲人一枚(学习中)27 分钟前
设计模式-创建型-建造者模式
java·设计模式·建造者模式
2202_7544215444 分钟前
生成MPSOC以及ZYNQ的启动文件BOOT.BIN的小软件
java·linux·开发语言
蓝染-惣右介1 小时前
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
java·数据库·tomcat·mybatis