J2EE项目实训 Spring框架技术——第11章 与Spring框架相关的设计模式(第1部分)
- 格式:pdf
- 大小:326.30 KB
- 文档页数:22
第11章与Spring框架相关的设计模式(第1/4部分)设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结————并且是在大量的实践中总结和理论化之后的优选的代码结构、编程风格及解决问题的思考方式。
Gamma、Helm、Johnson和Vissides四人团(GoF)在他们的“Design Patterns:Elements of Reusable Object-Oriented Software ,1995(中文版《设计模式:可复用面向对象软件基础》,机械工业出版社,2000年9月)”一书中介绍了23种模式的具体编程实现。
在应用系统的开发中,如果合理地应用相关的设计模式,可以避免在开发软件时少走弯路、可以获得系统设计的灵感,因为可以借鉴前辈大师的成功的经验。
从而有可能开发出具有良好的灵活性、可维护性、可移植性以及安全性的企业级的应用系统。
当然,如果要求每个软件开发者都去学习和掌握设计模式,可能对一般的开发者来说,在学习和具体的应用方面会存在一定的难度,而且也无此必要!应用系统的开发者,更应该把主要的学习和开发的精力放在本行业的业务功能的实现方面(成为领域专家),而对于具体的技术性的问题的解决可以依赖于计算机技术专家来帮助解决和实现(成为技术专家)。
Spring框架的设计者,基于这样的思路和考虑,在Spring框架中对GOF中的许多设计模式进行包装和简化。
从而使得Spring框架的使用者不用再具体地关心或者了解这些设计模式的具体编程细节。
在本章为了让读者对Spring框架中包装了哪些设计模式、以及这些设计模式是如何具体地编程实现、应用在什么场景下等方面的知识有所了解。
系统地介绍与Spring框架相关的设计模式。
1.1工厂模式1.1.1GOF设计模式中的工厂模式1、工厂模式应用工厂模式可以达到能够实现应用系统中的数据层和业务逻辑层的分离的目标,因为在业务层中可以不需要关心数据层的对象的具体创建的实现细节。
也就是达到分离对象的创建者和对象的使用者之间的职责,从而使得在系统架构设计中的应用多层架构和分层等方面的概念和技术要求能够得以真正地实现。
(1)工厂模式在GOF的设计模式中属于创建型模式在GOF的设计模式的划分中,把与实现对象的实例化相关的模式称之为“创建型模式”。
当然下面所要讨论的工厂模式其实为创建型模式中的一种实现形式。
在应用和学习各种设计模式时,开发者在编程时应该遵守一个基本的要求是“面向接口编程实现”。
因为这些模式的示例代码,都是采用面向接口编程实现的。
面向接口编程要求针对接口提供对应的实现类,而不是针对具体的目标类编程实现。
因为在面向对象的编程技术中的接口主要是提供调用规则或者功能实现的要求,而接口的实现类则是完成接口中所规定的功能行为的具体实现者。
(2)什么是工厂模式工厂模式主要是为创建对象提供一种统一的接口,并且封装创建对象的具体实现的细节过程,使得对象的使用者在调用一个对象时,根本无需关心这个对象实例是如何产生的。
也即要达到将创建对象实例的职责与使用该对象实例的职责相互分开的目的。
2、工厂模式的具体应用的形式工厂模式分为工厂方法模式和抽象工厂模式,两者主要的区别是:(1)工厂方法模式是创建一种产品接口下的产品对象,也就是通常意义下所理解的单一产品系列的工厂。
(2)而抽象工厂模式是创建多种产品接口下的产品对象,也就是通常意义下所理解的多个产品系列的工厂。
开发者在具体应用这两种不同实现方式的工厂模式时所应该注意的是,这两种具体应用的形式没有很明显的本质上的区别,它们之间在具体应用方面的区别在于开发者所需要创建对象的复杂程度上。
如果开发者创建对象的方法变得比较复杂了,一般就可能要采用抽象工厂模式,这样能够将对象创建时的共同行为的代码部分封装在抽象类中,而不同功能实现要求的代码部分则可以通过使用子类来实现。
3、为什么工厂模式在应用开发中是如此常用?因为工厂模式就相当于面向对象编程中的创建对象实例的new(生产或者创建出某一对象产品)语句,在应用系统中经常要根据某个特定的类来生成该类的对象实例,如:TVProduct myTVSet=new TVProduct() 。
而GOF设计模式中所提及的工厂模式也是用来创建类的对象实例的。
在应用系统的编程开发实现时,对使用new语句来创建对象的各种应用,应该考虑是否可以应用工厂模式来代替并加以对对象的创建方式进行优化。
尽管在编程实现方面可能会出现多编程一些程序代码,但会给应用系统在以后的系统扩展方面带来更好的可扩展性、和在系统维护中尽量少的代码的修改量。
4、应用工厂模式时将会有如下三个主要的缺点(1)除非重新编译,否则无法对产品的实现类进行替换必须重新编译工厂类使得原本可以达成的易用性将大大地被降低。
在早期的软件开发实践中,开发者一般是通过引入可配置化工厂类的方式,为这种基于接口的设计提供足够的支持。
这解决了对象实例化的问题,但是它为应用系统的开发带来了一定的额外负担;同时,它也没有真正帮助开发者解决工厂模式所存在的下面的两个问题。
(2)无法透明地为不同组件提供多个实现这是开发者在应用工厂模式时一个比较棘手的事情,因为工厂类要求每个组件都必须遵从工厂类中定义的方法和结构特征。
当然开发者可以在代码的实现的形式上为工厂类中的creatorProduct(int productKind)方法增加一个参数,通过该参数达到对接口实现的不同版本进行索引。
这种实现方式的问题在于开发者必须担负很大的维护工作量,每个组件都必须使用一个不同的关键字。
从而使得它必须以一种与众不同的方式与其他组件的实例相区分。
(3)无法简单地在单例或者原形之间切换产品的对象实例产生的模型本章节所给出的各个示例的代码是实现了返回多个产品对象实例的方式(原形方式),如果系统需要提供一个单例(Singleton)的对象实例,此时开发者也必须需要重新修改并编译工厂类中的代码。
存在这个问题的核心是在于组件必须主动寻找接口的实现类,因此这个问题并不能通过传统的工厂模式加以解决。
而在Spring框架中,只需要修改一下Spring框架IoC容器的XML文件中的对象的创建方式的要求的属性,就可以动态地进行切换。
1.1.2工厂模式中的工厂方法模式1、工厂方法(Factory Method) 模式的作用当然其作用也应该是前面所描述的工厂模式的通用的作用,也就是同样能够实现将创建对象的实例的工作与使用对象实例的工作分开。
这样的基本目的其实是更好地应用面向对象的封装(Encapsulation)和分派(Delegation)原则以及该原则的具体应用。
消费者(也就是对象的使用者程序)在任何时候需要某种产品(也就是对象的使用者程序中所需要的目标对象),只需要向工厂类(其实它是中间的代理作用的类)请求即可。
消费者无须修改代码或者无需关心目标对象的创建实现的过程细节就可以应用产品对象。
但在应用工厂模式时,也包括工厂方法模式的主要缺点是当目标产品类需要修改或者扩展时,对应的工厂类也要做相应的修改。
因此,工厂类与产品类之间是紧密藕合的,而产品类的使用者(消费者)与产品之间是分离的!2、在什么应用场合下应该应用工厂方法模式开发者可以考察应用系统中对所创建出的对象的具体要求,如果当一个类(消费者)不知道它所必须创建的对象的类(产品类)的时候、或者当一个类希望由它的子类来指定它所创建的对象的时候,可以应用工厂方法模式。
3、工厂方法模式中所涉及的标准的UML类图(1)GOF设计模式中的工厂方法模式经典的UML类图下面的图11.1为GOF设计模式中的工厂方法模式经典的UML类图,本书在此加以引用。
图11.1工厂方法模式中所涉及的标准的UML类图(2)主要的几个角色的对象从其UML的类图中可以发现出,在工厂方法模式中主要存在下面的几个角色的对象:1)产品的接口Product,定义产品的具体功能的要求2)产品的接口Product的具体实现类ConcreteProduct(可以允许为多个)3)产品的创建者工厂类Factory(也可以规定其接口)4)产品的使用者(消费者)或者客户类(ProductUser)4、工厂方法模式的程序代码示例为了让读者对工厂方法模式的具体编程实现有所了解和掌握,下面首先给出一个模式的原理性的示例,然后再给出一个具体的实际应用的示例。
(1)定义出一个产品的抽象类或者接口,以规定出该产品的主要功能要求【例11-1】产品的抽象类或者接口定义的代码示例public abstract class Product{public abstract void makeFunction();}(2)根据产品的接口产生出不同的特殊产品也就是对前面的产品接口中的主要功能要求加以具体的实现类,在下面的示例中给出两种不同的产品的具体实现类的代码。
从实现类代码的示例中,可以了解到可以针对同一个产品的接口提供多个不同的产品实现类以满足客户的不同的应用需要。
当客户端程序或者产品的消费者程序有实现新的功能的产品对象的需求时,只需要为该接口增加一个新的实现类。
这样,应用系统在扩展时相对比较方便。
【例11-2】产品接口的某个实现类的代码示例public class TVSet extends Product {public void makeFunction() {}}【例11-3】产品接口的另一个实现类的代码示例public class Monitor extends Product {public void makeFunction() {}}(3)定义出制造产品(也就是创建产品类的对象实例)的工厂类在该工厂类中,根据客户端程序所请求的产品的类型的不同要求,相应地创建出某种具体产品类的对象实例,并返回给客户程序。
因此,通过工厂类可以隔离产品类和产品的使用者之间的关系。
【例11-4】工厂类的代码示例public class Factory{public static final int TVSet_Product=1;public static final int Monitor_Product=2;public static Product creatorProduct(int productKind) {if (productKind ==1) {return new TVSet();}else if (productKind ==2) {return new Monitor();}}}在工厂类中应该注意在编程实现方面的一些要求,产品的创建方法(本示例为creatorProduct)一般为静态(static)方法,同时该方法的返回值在声明时应该为产品的接口类型的对象;同时该方法一般也应该带上某个参数,该参数规定具体所需要的产品对象的类型。