Java设计模式结合Spring源码案例(一)|策略模式+工厂模式

Java设计模式结合Spring源码案例(一)|策略模式+工厂模式



前言

  年初前几个月全刷了一遍Head First系列的设计模式(学渣表示三个月才看完一本书😂😂),当时自己看完对于系统架构设计以及代码层设计都有了非常深刻的认识和理解。Head First系列书特色是采用引导式教学,不直接告诉你怎么做,而是利用故事带领读者思考并解决问题(经历过教科式的十六年教育,刚看这本书风格还真不习惯🤣🤣)看完本书后一直想写博客总结下现有的主要设计模式以及各设计模式代码案例,前面由于忙于迁移更新博客花费了了较多时间,从这篇文章开始讲会总结每本书看完后的自己的知识总结和认识理解,如有不当,敬请指正,谢谢!

我的github主页地址 https://xdj68.github.io


一、设计模式简介

  设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

  设计模式是一套被反复使用的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式使代码编制真正工程化,合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。


二、设计模式原则

  Java是面向对象的编程语言,其中包括四种OO基本概念:抽象,封装,继承,多态。设计原则同样面向对象设计,其中包含九大OO基本原则:

  • 封装变化
  • 多用组合,少用继承
  • 针对接口编程,不针对实现编程
  • 为交互对象之间的松耦合设计而努力
  • 开闭原则(Open Close Principle)—类应该对扩展开放,对修改关闭
  • 依赖倒置原则(Dependency Inversion Principle)—依赖抽象,不要依赖具体类
  • 最少知识原则(Least Knowledge Principle)—只和朋友交谈
  • 好莱坞原则(Hollywood Principle)—别找我,我会找你
  • 单一责任原则(Single Responsibility Principle)—类应该只有一个改变的理由

三、设计模式类型

  设计模式主要包括23种类型,这些模式可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns),我们还会讨论业务类型的设计模式:J2EE 设计模式。

命令描述
创建型模式
  • 工厂模式(Factory Pattern)
  • 抽象工厂模式(Abstract Factory Pattern)
  • 单例模式(Singleton Pattern)
  • 原型模式(Prototype Pattern)
结构型模式
  • 适配器模式(Adapter Pattern)
  • 桥接模式(Bridge Pattern)
  • 过滤器模式(Filter、Criteria Pattern)
  • 组合模式(Composite Pattern)
  • 装饰器模式(Decorator Pattern)
  • 外观模式(Facade Pattern)
  • 蝇量模式(Flyweight Pattern)
  • 代理模式(Proxy Pattern)
行为型模式
  • 责任链模式(Chain of Responsibility Pattern)
  • 命令模式(Command Pattern)
  • 解释器模式(Interpreter Pattern)
  • 迭代器模(Iterator Pattern)
  • 中介者模式(Mediator Pattern)
  • 备忘录模式(Memento Pattern)
  • 观察者模式(Observer Pattern)
  • 状态模式(State Pattern)
  • 策略模式(Strategy Pattern)
  • 模板模式(Template Pattern)
  • 访问者模式(Visitor Pattern)
J2EE 模式
  • MVC 模式(MVC Pattern)
  • 业务代表模式(Business Delegate Pattern)
  • 组合实体模式(Composite Entity Pattern)
  • 数据访问对象模式(Data Access Object Pattern)
  • 前端控制器模式(Front Controller Pattern)
  • 拦截过滤器模式(Intercepting Filter Pattern)
  • 服务定位器模式(Service Locator Pattern)
  • 传输对象模式(Transfer Object Pattern)

四、设计模式之策略模式

4.1 .策略模式简介

定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户

在这里插入图片描述

五、设计模式之工厂模式

5.1 工厂模式简介

  工厂模式主要分为俩种:抽象工厂和工厂方法。
  PS:简单工厂就是封装严格来说属于策略模式。

5.2. 抽象工厂简介

提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类

在这里插入图片描述

5.3. 工厂方法简介

定义了一个创建对象的接口,但由子类决定需要实例化哪一个类。工厂方法把类的实例化延迟到子类执行

在这里插入图片描述

5.4. Spring案例: BeanFactory简介

  首先介绍下下Spring Bean的生命周期:

5.4.1 Spring Bean 的生命周期简介

Spring Bean 需要在容器启动时根据 Java 或 XML Bean 定义进行实例化。框架可能还需要执行一些初始化前和初始化后的步骤以使 Bean 进入可用状态,当不再需要 Bean 时会将其从 IoC容器中移除。同时与初始化阶段一样,Spring 框架可能需要执行销毁前和销毁后的步骤以释放其他系统资源。Spring Bean工厂负责管理在 Spring 容器中创建的 Bean 的生命周期回调。

5.4.2 Spring Bean 的生命周期过程

在这里插入图片描述

  • 1 加载Bean 定义规范
  • 2 依赖注入 a.实例化Beans b.调用setter进行属性赋值
  • 3 BPP创建初始/销毁Beans
5.4.3 Spring Bean 的生命周期回调

在这里插入图片描述

Spring Bean工厂负责管理在 Spring 容器中创建的 Bean 的生命周期回调,主要可以归类为俩大类:
Post-initialization 后-初始回调方法
Pre-destruction 前-销毁回调方法

  实现Bean生命周期的回调主要存在以下四种方式:

  • a. 实现回调InitializingBean接口-重写afterPropertiesSet() 方法 实现回调DisposableBean接口-重写destroy()方法
  • b. 实现回调Aware接口-例如:BeanNameAware 创建该Bean工厂中指定名字
  • c. XML配置Bean属性 init-method destroy-method
  • d. 新增注解@PostConstruct @PreDestroy

  建议采用XML配置Bean属性和注解方式可以更加灵活进行变更配置

在这里插入图片描述

5.4.4 BeanFactory 整体类结构UML简介

Spring IoC 容器是 Spring Framework 的核心。容器将创建对象,将它们连接在一起,配置它们,并管理它们从创建到销毁的完整生命周期。Spring 容器使用依赖注入 (DI) 来管理组成应用程序的组件。 Spring 提供了以下两种类型的容器:
BeanFactory 容器
应用上下文容器
在这里插入图片描述

5.4.5 BeanFactory 中的 抽象工厂 设计模式应用
  • DefaultListableBeanFactory 是Bean工厂的一个默认实现
  • StaticListableBeanFactory是简化版的DefaultListableBeanFactory由于未实现BeanDefinitionRegistry,所以不支持BeanDefinition的注册操作
  • BeanFactory提供一个接口,用于创建相关工厂的家族
  • DefaultListableBeanFactory和StaticListableBeanFactory是具体实现类,属于抽象工厂设计模式,目的就是集中管理SpringBean的实例化、定位、配置及依赖

在这里插入图片描述

在这里插入图片描述

5.4.6 BeanFactory 中的 工厂方法 设计模式应用
  • AbstractBeanFactory 是的BeanFactory的抽象基类,目的是获取Bean规范定义
  • AbstractAutowireCapableBeanFactory是实现默认Bean创建的抽象工厂超类
  • AbstractBeanFactory定义了一个创建对象的接口,抽象方法createBean是为了合并Bean规范定义创建Bean实例,所有的Bean检索方法都委托此方法进行实际的Bean创建
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException;

}

  AbstractAutowireCapableBeanFactory是AbstractBeanFactory 的子类,由子类决定实例化Bean,属性赋值,应用BPP等操作。工厂方法把类的实例化延迟到子类执行,属于工厂方法的设计模式,目的是由子类控制创建Bean实例过程。

@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		if (logger.isTraceEnabled()) {
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

  AbstractBeanFactory 定义了一个创建对象的接口,抽象方getBeanDefinition是为了BeanFactory返回给定名字的Bean规范定义

protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;

  DefaultListableBeanFactory是AbstractBeanFactory 的子类,由子类决定返回给定名字的Bean规范定义。工厂方法把类的实例化延迟到子类执行,属于工厂方法的设计模式,目的是由子类控制给定名字的Bean规范定义过程。

@Override
	public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		BeanDefinition bd = this.beanDefinitionMap.get(beanName);
		if (bd == null) {
			if (logger.isTraceEnabled()) {
				logger.trace("No bean named '" + beanName + "' found in " + this);
			}
			throw new NoSuchBeanDefinitionException(beanName);
		}
		return bd;
	}

在这里插入图片描述

总结

  好的开始是成功的一半,终于写完了策略模式(封装不多讲)和工厂模式在Spring Bean生命周期中的简单应用。下篇继续研究下Spring源码做其他设计模式的分析,由于此系列是讲设计模式,Spring源码分析略带而过,后期准备写完整的Spring源码分析篇(希望能写到Spring源码初步掌握那天😄😄,给吊车尾的自己加加油,未来的路还很长💪💪!)

  工作搬砖简单坚持写博客难,希望能够坚持有时间写一写文章,积累下遇到的问题和解决方式以及知识点总结!!

我的github主页地址 https://xdj68.github.io


参考文档:
https://howtodoinjava.com/spring-core/spring-bean-life-cycle https://www.zhihu.com/question/38597960
Head of First 设计模式

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个使用策略模式案例: 假设我们有一个订单处理系统,订单可以使用不同的支付方式进行支付,包括微信、支付宝和银行卡。在原始实现中,我们需要使用if else语句来判断不同的支付方式。这样会导致代码的可读性和可维护性降低,因为每次新增或修改支付方式都需要修改if else代码段。 现在,我们使用策略模式来重构这个系统。首先,我们定义一个支付接口`PaymentStrategy`,并在接口中定义了一个`pay()`方法: ```java public interface PaymentStrategy { public void pay(double amount); } ``` 然后,我们实现不同的支付方式,包括微信支付、支付宝支付和银行卡支付: ```java public class WechatPayment implements PaymentStrategy { public void pay(double amount) { System.out.println("使用微信支付 " + amount + " 元"); } } public class AlipayPayment implements PaymentStrategy { public void pay(double amount) { System.out.println("使用支付宝支付 " + amount + " 元"); } } public class CreditCardPayment implements PaymentStrategy { public void pay(double amount) { System.out.println("使用信用卡支付 " + amount + " 元"); } } ``` 接下来,我们定义一个订单处理类`OrderService`,并在类中注入支付策略`PaymentStrategy`: ```java public class OrderService { private PaymentStrategy paymentStrategy; public OrderService(PaymentStrategy paymentStrategy) { this.paymentStrategy = paymentStrategy; } public void processOrder(double amount) { paymentStrategy.pay(amount); } } ``` 最后,我们在Spring配置文件中定义不同的支付策略,然后使用`@Autowired`注解来注入不同的支付策略: ```xml <bean id="wechatPayment" class="com.example.payment.WechatPayment" /> <bean id="alipayPayment" class="com.example.payment.AlipayPayment" /> <bean id="creditCardPayment" class="com.example.payment.CreditCardPayment" /> <bean id="orderService" class="com.example.order.OrderService"> <constructor-arg> <ref bean="wechatPayment" /> </constructor-arg> </bean> ``` 现在,我们可以通过修改Spring配置文件来切换不同的支付方式,而不需要修改业务逻辑代码。这样,我们就使用策略模式来减少了if else语句的使用,提高了代码的可读性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xdj68

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值