信息工程是以当前数据系统为基础,在一个企业或企业的主要部门,关于建设信息系统的规 划、分析、设计和构成的一整套相互关联的正规化、自动化的技术应用。——James Martin
正如上面信息工程的创始人James Martin为信息工程的概念所做定义类似,模式(Patterns)的创始人建筑师Christopher Alexander在<模式语言,1977、1979>一书中对模式的概念进行了如下描述(附注:书名后面的年份代表在各个不同时期的作品,下面形式同上):每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次的使用该解决方案而不必做重复劳动。每个模式是由三部分组成的一个规则,这个规则描述特定环境、问题和解决方案之间的关系。简单的说,没有一个模式是独立的实体,每个模式都存在着相互支持,但支持的程度不同:大的模式可以内嵌小的模式,同等层次的模式并列存在,而小的模式被嵌入到大的模式之中。——Christopher Alexander
模式的概念在软件行业被采用以后,得到的广泛的发展,现在已经存在许多种类型的模式应用,其中比较有名的箸作有:GoF(Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四人,简称:Gang of Four[GoF])的<设计模式,1995>,Martin Fowler的<分析模式,1997>,Frank Buschmann等人的<体系结构模式,1996、2000>、Jim O.Coplien、Niel Harrison等人的<编程模式,1995、1996、1998、1999>和Deepak Alur等人的等,其中最具影响的是GoF的<设计模式>一书,书中详细讨论了三种类型,共23种模式。好的设计源于工作中经验的积累,当设计使用标准的模板以模式的方式进行交流时,模式就成了交流和重用的强大机制,并且可以改善设计和开发软件的方式。模式可以帮助我们在一个特定的环境里整理并记录已知的可重现的问题及解决方案,并且通过模式来与他人交流这些知识,这些模式可以解决在不同环境中重复出现的问题。模式可以使设计重复使用,重复使用已知的解决方案可以缩短设计和开发应用的周期,有效的使用模式,可以使我们远离重复投资的怪圈。模式的关键在于简单性和可重现性。
举一个模式应用的简单示例。例如,在你的便携式电脑上运行一个进程中的对象,并且这些对象需要和运行在另一进程中的别的对象通信,也许这一进程并不在你的便携式电脑上,而在别的地方。你又不想让系统中的对象担心如何找寻网上的其他对象或者执行远程过程调用。这时,可以使用代理(Proxy模式,详见GoF的<设计模式>一书)模式来解决这个问题,你能做的事就是为这个远程对象在你的本地过程中建立一个代理对象,该代理对象和远程对象具有相同的接口。你的本地对象利用通常处理过程中的消息发送来和代理交谈。这时代理对象负责把消息传送给实在对象,而不管实在对象位于何处。
由于下面要讲的Java 2平台的企业版(J2EE)应用模式中很多用到了设计模式与重构(Refactoring)的概念,所以在此有必要再概要介绍一下重构的概念。重构已经被证明可以阻止软件的腐朽和衰败,关于重构方面的有名箸作当然首推是Martin Fowler所写的<重构,1999>一书了,书中详细介绍了重构的七大类型,共70余种具体的重构手法,同时也指出测试机制在重构中的重要性。书中Martin Fowler对重构的概念进行了详细说明:构是对软件内部结构的一种调整,目地是在不改变[软件之可察行为]的前提下,提高其可理解性,降低其修改成本。重构是一种有纪律的、经过训练的、有条不紊的程序整理方法,可以将整理过程中不小心引入的错误的机率降到最低,本质上说,重构就是在代码写好之后改进它的设计。重构之前,首先检查自己是否有一套可靠的测试机制,这些测试必须有我检验能力。—— Martin Fowler
建立于Java编程语言和Java技术基础之上的J2EE平台是最适用于企业级分布式环境的应用结构,它被设计为面向多层体系的结构。J2EE包含下面关键技术:Java服务器页面(Java Service Page,JSP)、Servlet、Enterprise JavaBeans(EJB)组件、Java消息服务(Java Message Service,JMS)、JDBC和Java命名与目录接口(Java Naming and Directory Interface,JNDI)。由于J2EE平台是分层系统,所以我们将J2EE的层次模型化,这个模型使得我们将职责逻辑地分到不同的层中,共分了五个层次:客户层、表示层、业务层、集成层和资源层。因为客户层和资源层并不是J2EE平台直接关注的问题,所以后面介绍的15个J2EE应用模式全部属于上面五层中的中间三层,其中表示层模式包含与Servlet和JSP技术相关的模式、业务层模式包含与EJB技术有关的模式、集成层模式包含与JMS和JDBC有关的模式。由于J2EE模式众多,篇幅有限,这里只概要介绍其中的一种应用模式 - 集成层的数据访问对象(DAO)模式,有兴趣的读者可以参看下面参考文献中的资料。
数据访问对象模式
1、问题
根据数据源不同,数据访问也不同。根据存储的类型(关系数据库、面向对象数据库等)和供应商不同,持久性存储(比如数据库)的访问差别也很大。当业务组件(如会话bean)或表示组件(如助手组件)需要访问某数据源时,它们可以使用合适的API来获得连接性,以及操作该数据源。但是在这些组件中包含连接性和数据访问代码会引入这些组件及数据源实现之间的紧密耦合。组件中这类代码依赖性使应用程序从某种数据源迁移到其它种类的数据源将变得非常麻烦和困难,当数据源变化时,组件也需要改变,以便于能够处理新类型的数据源。
2、解决方案
使用数据访问对象(DAO)来抽象和封装所有对数据源的访问。DAO管理着与数据源的连接以便于检索和存储数据,DAO实现了用来操作数据源的访问机制。依赖于DAO的业务组件为其客户端使用DAO提供了更简单的接口,DAO完全向客户端隐藏了数据源实现细节。由于当低层数据源实现变化时,DAO向客户端提供的接口不会变化,所以该模式允许DAO调整到不同的存储模式,而不会影响其客户端或业务组件。重要的是,DAO充当组件和数据源之间的适配器。
3、实现策略
通过调整抽象工厂(Abstract Factory)模式和工厂方法(Factory Method,这二个创建型模式的实现详情可参看GoF的<设计模式>一书)模式,DAO模式可以达到很高的灵活度。
当低层存储不会随着实现变化而变化时,可以使用工厂方法模式来实现该策略,以产生应用程序需要的大量DAO,如下面类图1所示。
当低层存储随着实现的变化而变化时,策略可以通过使用抽象工厂模式而实现。抽象工厂可以基于工厂方法实现而创建,并可使用工厂方法实现,该策略提供一个DAO的抽象工厂对象,其中该对象可以构造多种类型的具体的DAO工厂,每个工厂支持一种不同类型的持久性存储实现。一旦你获取某特定实现的具体DAO工厂,你可以使用它来生成该实现中所支持和实现的DAO,如下面类图2所示。
4、应用
当数据访问代码被直接嵌入到有其他不相关职责的某类中时,就会使修改变的十分困难。这时可以采用分离数据访问代码的解决方案,将数据访问代码抽取到一个新类中,并且把该新类逻辑或者物理地移动到离数据源比较近的位置,这样可以增强模块性和可重用性,如下面图3所示。具体作法可以使用提炼类(Extract Class,一种重构手法,细节可参看Martin的<重构>一书)方法创建一个新类,并将原来类中把数据访问代码移动到这个新的数据访问对象(DAO)类,使用这个新的DAO对象从控制器类中访问数据。
示例:持久性逻辑被嵌入到一个使用新DAO对象管理的持久性的某企业新DAO对象中,把持久性代码和该企业新DAO对象代码结合起来会创建脆弱的、紧密耦合的代码。当持久性代码是该企业新DAO对象的一部分时,对该持久性存储的任何改动都要求更改该新DAO对象的持久性代码。这种耦合对企业新DAO对象代码维护会带来负面的影响。
在15个J2EE模式中,每个模式都作用于设计模式和构架模式之间的某些方面。每个模式不是孤立存在的,需要其它模式的支持才能更加体现其含义和用处,为了最大限度的用好模式,还需要充分理解模式之间的关系。