摘要: 我相信很多在刚刚使用Spring的同事会考虑一个问题:我们为什么要用Spring,Spring虽然给我们带来了一些好处,可是,似乎好处似乎不是那么明显。IOC的作用似乎也很牵强。
1.前言我相信很多在刚刚使用Spring的同事会考虑一个问题: 我们为什么要用Spring,Spring虽然给我们带来了一些好处,可是,似乎好处似乎不是那么明显。IOC的作用似乎也很牵强。 所以,冷凝沙漠在此记录了自己的一些Spring开发经验,与各位分享。 2.一个常见的业务场景
|
publicclass Example1 { publicstaticvoid main(String[] args) { String specialParam = args[0];// 这是一个特定的参数
Object[] param1 = new Object[] {}; Object[] param2 = new Object[] {}; Object[] param3 = new Object[] {}; // ………… 以上是一堆常见、有规则的其他参数
if ("CanShu1".equals(specialParam)) {
// ………… 一堆冗长的程序
} elseif ("CanShu2".equals(specialParam)) { // ………… 又一堆冗长的程序
} elseif ("CanShu3".equals(specialParam)) {
// ………… 再一堆冗长的程序
} else {
// ………… 其他默认的冗长的程序 } } } |
2.3.优缺点分析
从这个示例的角度,代码挺清晰的,但是到了实际应用中,可能就会有数十套逻辑,可能会有长达数千行代码,可能会绕晕很多人。
3.一个常见的不好的修改方式
3.1.场景简介与代码示例
如下是很常见的一个修改方式,将不同的流程提炼出独立的方法,让逻辑判断的位置独立出来。
publicclass Example2 {
publicstaticvoid main(String[] args) { String specialParam = args[0];// 这是一个特定的参数
Object[] param1 = new Object[] {}; Object[] param2 = new Object[] {}; Object[] param3 = new Object[] {}; // ………… 以上是一堆常见、有规则的其他参数
// 提炼独立方法 if ("CanShu1".equals(specialParam)) { handleCanShu1(param1, param2, param3); } elseif ("CanShu2".equals(specialParam)) { handleCanShu2(param1, param2, param3); } elseif ("CanShu3".equals(specialParam)) { handleCanShu3(param1, param2, param3); } else { handleDefault(param1, param2, param3); } }
publicstaticvoid handleCanShu1(Object[] param1, Object[] param2, Object[] param3) { // ………… 一堆冗长的程序 }
publicstaticvoid handleCanShu2(Object[] param1, Object[] param2, Object[] param3) { // ………… 又一堆冗长的程序 }
publicstaticvoid handleCanShu3(Object[] param1, Object[] param2, Object[] param3) { // ………… 再一堆冗长的程序 }
publicstaticvoid handleDefault(Object[] param1, Object[] param2, Object[] param3) { // ………… 其他默认的冗长的程序 } } |
3.2.优缺点分析
相信各位维护的旧项目里面不会缺乏此类代码。
从维护的角度来看:
1.如果要继续更新这个代码,也只能不断的在这个类上下功夫。很可能这个类未来会变成一个“只有上帝知道它是干嘛的”的复杂类。
2.必须要有源码才能更新代码,才能重新编译。相信我,很多维护方没有源代码,这种修改对于程序员而言属于“Mission Impossible”。当然,对于搞IT的,天天玩程序员版的碟中谍,也是家常便饭。
因此,大部分Java培训师、Team Leader、代码走查员都会说:这样不好,这样不好!
4.中规中矩的工厂模式
4.1.场景简介
从模式的角度来看,工厂模式自然是这里最适合的模式:
咱们先提炼一个公共的接口,定义一个调用的工厂,再不断实现这个接口,并将接口注册到工厂。
未来如果要增加一种业务,就单独增加一个实现类,并注册到工厂就行了。
4.2.代码示例
以下是一套简单的实现代码:
publicclass Example3 { publicstaticvoid main(String[] args) { String specialParam = args[0];// 这是一个特定的参数
Object[] param1 = new Object[] {}; Object[] param2 = new Object[] {}; Object[] param3 = new Object[] {}; // ………… 以上是一堆常见、有规则的其他参数 Example3Service service = Example3Factory.getService(specialParam); service.run(param1, param2, param3);
} } |
调用其实是很简单的。
package com.test; /** * 提炼出工厂和接口 */ publicclass Example3Factory { publicstatic Example3Service getService(String specialParam) { if ("CanShu1".equals(specialParam)) { returnnew Example3ServiceCanShu1Impl(); } elseif ("CanShu2".equals(specialParam)) { returnnew Example3ServiceCanShu2Impl(); } elseif ("CanShu3".equals(specialParam)) { returnnew Example3ServiceCanShu3Impl(); } else { returnnew Example3ServiceDefaultImpl(); } } } |
工厂类可以简单的如例子中写死,也可以写成collection形式,然后进行注册。
package com.test; /** * 提炼出工厂和接口 */ publicinterface Example3Service { publicvoid run(Object[] param1, Object[] param2, Object[] param3); }
|
接口神马的最简单了,以下就是接口实现:
package com.test;
publicclass Example3ServiceCanShu1Impl implements Example3Service { publicvoid run(Object[] param1, Object[] param2, Object[] param3) { // ………… 一堆冗长的程序 } } |
package com.test;
publicclass Example3ServiceCanShu2Impl implements Example3Service { publicvoid run(Object[] param1, Object[] param2, Object[] param3) { // ………… 又一堆冗长的程序 } } |
package com.test;
publicclass Example3ServiceCanShu3Impl implements Example3Service { publicvoid run(Object[] param1, Object[] param2, Object[] param3) { // ………… 再一堆冗长的程序 } } |
package com.test;
publicclass Example3ServiceDefaultImpl implements Example3Service { publicvoid run(Object[] param1, Object[] param2, Object[] param3) { // ………… 其他默认的冗长的程序 } } |
4.3.优点分析
形成工厂模式的优点很明显:
l提供创建对象的接口. 为系统结构提供了非常灵活强大的动态扩展机制,只要我们更换一下具体的工厂方法,系统其他地方无需一点变换,就有可能将系统功能进行改头换面的变化。
l除了工厂类以外的程序都不需要去了解具体的实现情况,所以给程序实现带来了很多方便。
l将程序的一部分复杂度集中在接口的实现上,一部分程序员可以专心于如何通过实现接口来实现业务逻辑,另一部分程序员可以专心于通过更新工厂注册方式来将新的实现对接到整个程序中。
4.4.缺点分析
形成工厂模式的缺点也很明显:
l工厂类依旧需要去了解具体的实现类以及其参数,当程序复杂度到一定程度时,工厂类依旧可能很复杂。
l还是必须要有源码才能更新工厂类的代码,才能重新编译。
5.开始引入Spring
5.1.场景简介
既然工厂模式的缺点集中在工厂上,那么就优化工厂好了。我们可以把工厂优化为抽象厂,也可拆掉这个工厂,用Spring来替代这个工厂。
可以这样想,工厂类就是提供了一个Map,根据一个特定的key值,找一个特定的Bean。如果仅仅是这样,Spring自身是不是就能作为这个工厂了?
5.2.代码示例
调用方的代码依旧很简单:
package com.test; import java.util.Map; import javax.annotation.Resource; publicclass Example4 { @Resource private Map<string,> example4ServiceMap; @Resource private Example4Service example4ServiceDefaultImpl;
publicvoid runMain(String specialParam) { Object[] param1 = new Object[] {}; Object[] param2 = new Object[] {}; Object[] param3 = new Object[] {}; // ………… 以上是一堆常见、有规则的其他参数
Example4Service service = example4ServiceMap.get(specialParam); if (service == null) { service = example4ServiceDefaultImpl; } service.run(param1, param2, param3); } } |
工厂的内容直接用Spring配置完成:
<!--?<-->xmlversion="1.0"encoding="UTF-8"?><!--?<--> <<>beansxmlns=http://www.springframework.org/schema/beans<!--<--> ……………… xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd …………">
<<>beanid="example4ServiceMap"<!--<--> class="java.util.HashMap"> <<>constructor-arg><!--<--> <<>map><!--<--> <<>entrykey="CanShu1"value-ref="example4ServiceCanShu1Impl"/><!--<--> <<>entrykey="CanShu2"value-ref="example4ServiceCanShu2Impl"/><!--<--> <<>entrykey="CanShu3"value-ref="example4ServiceCanShu3Impl"/><!--<--> <<!--</span-->map> <<!--</span-->constructor-arg> <<!--</span-->bean>
<<!--</span-->beans> |
接口以及其实现类没有啥变化,只是多了些注解而已。当然,需要好好管理Spring中的Bean:
package com.test; /** * 提炼出工厂和接口 */ publicinterface Example4Service { publicvoid run(Object[] param1, Object[] param2, Object[] param3); } |
实现这里就只多了个注解:
package com.test; import org.springframework.stereotype.Service;
@Service publicclass Example4ServiceCanShu1Impl implements Example4Service { publicvoid run(Object[] param1, Object[] param2, Object[] param3) { // ………… 一堆冗长的程序 } } |
package com.test;
import org.springframework.stereotype.Service;
@Service publicclass Example4ServiceCanShu2Impl implements Example4Service { publicvoid run(Object[] param1, Object[] param2, Object[] param3) { // ………… 又一堆冗长的程序 } } |
package com.test;
import org.springframework.stereotype.Service;
@Service publicclass Example4ServiceCanShu3Impl implements Example4Service { publicvoid run(Object[] param1, Object[] param2, Object[] param3) { // ………… 再一堆冗长的程序 } } |
package com.test;
import org.springframework.stereotype.Service;
@Service publicclass Example4ServiceDefaultImpl implements Example4Service { publicvoid run(Object[] param1, Object[] param2, Object[] param3) { // ………… 其他默认的冗长的程序 } } |
5.3.优缺点分析
这个方法的优点在于,不需要代码书写工厂类了,只是一个简单的XML配置文件,就搞定了,因此,将新类注册到整个程序时,也就不需要源码、编译之类的,如果没有特殊情况,只要编译实现类就行了。
6.进一步简单化
6.1.场景简介
那能不能更简单一些呢?
能!
6.2.代码示例
调用方的稍微调整一下,会更简单:
package com.test;
importjava.util.Map;
import javax.annotation.Resource;
import……………….SpringUtil;
publicclass Example5 {
@Resource private Example5Service example5ServiceDefaultImpl;
publicvoid runMain(String specialParam) { Object[] param1 = new Object[] {}; Object[] param2 = new Object[] {}; Object[] param3 = new Object[] {}; // ………… 以上是一堆常见、有规则的其他参数
Example5Service service = (Example5Service) SpringUtil.getBean("example5Service" + specialParam + "Impl"); if (service == null) { service = example5ServiceDefaultImpl; } service.run(param1, param2, param3); } } |
仅仅是将调用方式微调一下,配置文件也就不需要了。
而接口和实现类则不会受到影响,不再重复粘贴了。
这里的SpringUtil在各个公司应该都有自己的简单实现,就不自己费力写了。
当然,事务之类的周边事宜还是需要各位自己在配置文件中好好管理起来的。
6.3.优缺点分析
到这个时候,程序已经初步从配置变成了流行的“规则”了。运维人员需要增加一个新业务时,只是需要保证类名保持一定的规则,而且Bean name在管理范围内,没有啥冲突,就行了。
7.后语
在此,冷凝沙漠只是记录了一个初步的思路来给大家启发大家思路。真正在程序开发的过程中需要比这更加细腻的设计过程。
希望这篇博文能解决大家在工作中遇到的问题。
相关推荐
在Spring框架中,工厂模式是核心的组件创建方式,它...总的来说,深入理解Spring工厂模式的实现有助于我们更好地掌握Spring框架的工作原理,从而能更高效地利用Spring进行开发,并且在遇到问题时能够迅速定位和解决。
**Spring中的IoC与工厂模式对比** 虽然简单工厂模式在某些场景下能有效地创建对象,但它仍然存在一定的局限性,比如不易扩展、违反开闭原则等。Spring的IoC容器则提供了更高级别的抽象,能够管理多个对象及其依赖...
在Spring框架中,我们可以利用其强大的IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)特性,将工厂模式与Spring相结合,以更加灵活和解耦的方式创建和管理对象。...
总结来说,Spring下的策略模式是实现灵活、可扩展性的关键,通过Bean工厂和依赖注入机制,我们可以轻松地在运行时切换策略,适应多变的需求。同时,结合源码学习能进一步提升对Spring框架的理解。
通过对Spring框架设计理念与设计模式的分析,我们可以看到Spring框架的成功在于其对软件工程原则的深刻理解和灵活应用。Spring不仅仅是一个简单的框架,它还是一个设计理念的典范,为开发者提供了强大而灵活的工具,...
3. **工厂方法模式(Factory Method)**:Spring AOP中的`ProxyFactory`是一个典型的工厂方法模式实现,它根据不同的条件创建不同的代理对象,将实例化推迟到子类,提供了更大的灵活性。 4. **原型模式(Prototype...
【标题】Spring02_工厂模式与Spring入门.zip 涉及的知识点主要围绕着软件设计模式中的工厂模式以及Spring框架的基础应用展开。这个压缩包内的资源,Spring02_工厂模式与Spring入门.wmv,可能是一个视频教程,旨在...
Java Spring代理模式AOP-IOC分析 一、代理模式概述 在软件设计中,代理模式是一种常用的设计模式。它可以在不修改原始代码的情况下,扩展或修改原始对象的行为。代理模式可以分为静态代理和动态代理两种。静态代理...
### Spring框架的设计理念与设计模式分析 #### 一、Spring框架概述 Spring作为一个现代软件开发领域内备受推崇的框架,其设计理念与设计模式一直是开发者关注的焦点。Spring框架旨在简化企业级应用程序的开发过程...
### Spring框架的设计理念与设计模式分析 #### 一、Spring框架概述 Spring作为一个现代软件开发领域内备受推崇的框架,其强大的功能与灵活性使得它在众多框架中脱颖而出。本文旨在深入探讨Spring框架的设计理念...
- **工厂模式**:Spring 作为bean工厂,负责创建和管理应用中的对象。 - **代理模式**:在AOP实现中,Spring 通过动态代理创建切面,实现了方法拦截。 2. **核心模块**: - **核心容器(Core Container)**:...
### Spring框架的设计理念与设计模式分析 #### 一、Spring框架概述 Spring作为一个顶级的Java开发框架,其设计理念和架构模式对于理解和应用该框架至关重要。本文将深入探讨Spring框架的核心设计理念,以及它如何...
在Spring中,工厂模式可以与IoC容器结合使用,例如在【springFactory】和【springFactoryJDOM】的示例中,我们可能会看到如何使用Spring的Bean工厂来创建和管理对象。Spring提供了XML配置和注解两种方式来声明和管理...
Spring 设计模式是软件设计模式在 Spring 框架中的应用,它们解决了软件设计中常见的问题,如工厂方法模式、代理模式、模板方法模式等。这些设计模式的应用使得 Spring 框架更加灵活、可扩展和可维护。 工厂方法...
本资源是spring的小例子程序,共包括以下7...工厂模式(factory) 模型视图控制器模式(MVC) 代理模式(proxy) 单例模式(singleton) 策略模式(strategy) 模板模式(template) 另外还有一个关于动态代理的小例子
Spring 框架的设计理念与设计模式分析 Spring 框架作为Java开发中最受欢迎的框架之一,其设计理念和设计模式的应用对于理解和优化软件设计具有重要意义。本文将深入探讨Spring的核心组件、设计理念以及其中蕴含的...
- **工厂模式**:Spring容器通过工厂模式创建和管理对象实例。 - **单例模式**:Spring中的bean默认是单例模式的,这意味着Spring容器只会为每个bean定义创建一个实例。 - **代理模式**:Spring AOP模块中使用了动态...