2008年9月28日星期日

Java 设计架构(一)


目录

摘要 ……………………………………………………………………2

文献综述 ………………………………………………………………3

第一章 前言……………………………………………………………6

第二章 OOP的基本原则及发展方向

第一节 软件的可维护性与可复用性…………………………6

第二节 六条OOP设计原则 ……………………………………7

第三节 AOP的兴起…………………………………………… 8

第三章 J2EE系统的架构设计

第一节J2EE中常用的概念……………………………………10

第二节 MVC架构 ………………………………………………12

第三节 分布式架构……………………………………………13

第四章 数据持久层的设计

第一节 业务对象的持久化……………………………………14

第二节 数据访问对象设计模式………………………………15

第三节 ORM框架的原理和重要性 ……………………………16

第四节 数据持久层……………………………………………19

第五节 数据库连接池、缓存及系统性能的提升 ……………21

第六节 Java反射技术  ………………………………………22

第五章 J2EE架构中各层的数据表示方法

第一节 MVC三层体系结构中的数据表示要求 ………………23

第二节 J2EE系统中各层数据表示的设计  …………………24

第六章 设计模式的概念与几种常用的J2EE设计模式

第一节 设计模式的概念………………………………………25

第二节 工厂创建模式与单例模式……………………………27

第三节 使用工厂模式实现DAO ………………………………31

总结 ……………………………………………………………………33

结束语 ………………………………………………………………34

多层J2EE系统的架构与模式设计

【摘要】   J2EE提供了一套完整的基于标准化模块的服务组件,它能自动的处理大多数应用程序的细节,而不需要复杂的编程,因此简化了复杂的企业级应用程序的开发。本文首先考察企业级应用的一般概念和需求,然后简要阐述面向对象程序设计的基本原则,并结合软件工程的思想来讨论多层的J2EE应用架构,分析它们满足企业级应用的方式,,再通过讲述常用的几种Java设计模式和Java反射技术来说明如何实现这些应用架构。

【关键词】 模型-视图-控制,对象关系映射,业务对象,面向方面编程,数据访问对象,设计模式

The Framework of Multitier J2EE System and Design Pattern

abstractsThe J2EE simplifies enterprise applications by basing them on standardized, modular components, by providing a complete set of services to those components, and by handling many details of application behavior automaticallywithout complex programming. This paper reviews the general concept and the requirement of enterprise application, elaborates the general principle of object oriented programming briefly. We combine the idea of Software-Engineering to discuss the framework of multitier J2EE, and meanwhile analyze how they can satisfy the demand of enterprise applications. At last, this paper shows how to implement those frameworks of multitier J2EE by introducing some kinds of Java design pattern and the Java reflection technology.

key wordsMVCORM BO AOP DAODesign pattern.

文献综述

计算机软件是人类心灵和智慧在虚拟空间中的投射。软件的性能是人类能力的扩展,它的活动就是人类心智活动的反映。软件直接表达出设计者对目标的理解,对用户的期待,以及对自己的定位。人们在自己的环境中不断发现问题和寻找问题的解决方案的时候,发现有一些问题及其解决方案不断变换面孔重复出现,但在这些不同的面孔后面有着共同的本质,这些共同的本质就是模式。著名建筑工程学家Christopher Alexander所著《建筑的永恒之道》( The Timeless Way of Building)和他发展出来的模式理论涵盖科学,心理,艺术和哲学,不仅适用于建筑工程学,而且适用于软件工程学以及任何其他的工程学。

今天的企业软件可以由多个不同的部分组成,但企业已经认识到,只要符合企业利益,很有必要将各个分散的系统进行良好的集成,以尽可能相互支持,总的来说企业希望对集成后的企业级软件的具体应用如下:

1.       通过集成企业的客户支持和本身的产品知识,企业可以利用WEB为它的客户提供更新更好的服务。

2.       将企业售货机联网,企业可以获得更多的在线客户。

3.       将销售管理系统和存货系统相链接,企业可以设计特定的低成本的Web销售渠道,这样可以进入未曾涉足的市场领域。

4.       如果给企业员工所使用的服务提供一个前端,例如内部办公用品订货系统,将它与会计系统连接在一起,企业就可以降低总体开支并提高员工的工作效率。

5.       在线使用企业HR系统,可以让员工根据他们自己的健康状况进行更多的选择,这样可以降低企业整体的管理费用。

6.       使企业的人力资源密集型操作自动化,并使它可用于任何时间任何地点,在降低整体运营费用的同时,企业还可以给它的客户提供更好的服务。

  按企业对企业级软件的要求,一个企业级应用系统(J2EE)肯定会是一个服务于商业目的,处理企业业务信息,数据的软件系统,因此大概可以总结出以下五方面的特征:有复杂的业务逻辑,有大量持久化数据,与多种外部系统相关联有较高的性能要求,在运行时需要随时监控,管理,应该能够实时记录,观察系统运行情况。修改系统配置。

以前的企业应用,集中式的单层(single tier)应用程序占有主导地位。在软件中,层是一个抽象概念,它的主要目的是通过将软件分解成独立的逻辑层,帮助我们理解与特定应用程序相关联的体系结构。从应用程序的角度看,单层应用程序的最大问题在于,它将表示,业务逻辑和数据都混合在一起。客户机-服务器方法通过将表示和一些业务逻辑分别移至单独的层中,缓解了上述主要问题的影响,不过从应用程序的角度来看,业务逻辑和表示依然很混乱。N层(n-tier)方法可以取得更好的整体平衡,它将表示逻辑与业务逻辑从底层数据中分离开来,以满足特定的需求。单单采用面向对象开发技术后只可以实现部分代码重用,原因之一是对象都细粒度化,正是因为细粒度对象间更紧密的耦合状态,从而便利大范围的重用变得很困难。分层化的组件设计就是为了解决这个问题。与对象不同,软件组件是在更高的抽象级中设计的,可以提供一个完整的功能或服务。组件间的耦合更为松散。利用组件的接口,可以将组件迅速组合在一起以构建更大的企业级应用程序。

近年来,人们已开发出了各种不同的帮助理解的组件模型,例如,Microsoft的ActiveX,后来的COM编程接口,和现在兴起的.net FrameWork,SUN Microsystems的applet和JavaBeans,Enterprise JavaBeans(EJB),其中EJB是J2EE的一部分。

Sun Microsystems把Java2平台组织成三个特定的,引人瞩目的版本:微型版(J2ME),标准版(J2SE)和企业版(J2EE)。在这些产品中,J2EE与开发企业级Java应用联系最紧密。J2EE为开发复杂的,分布式企业级Java应用定义了一套体系结构。

J2EE最初是由Sun Microsystems在1999年中期发布的,其正式发布则在1999年后期。J2EE仍然较新,其依次发布的版本间仍然存在着重大的改变,特别是在EJB方面。该平台是建立在Java"一次编写,随意运行"的理念上的,它通过一组技术和一套API实现。

N层体系结构的概念已经出现一段较长的时间了,并已成功地应用于构建企业级应用程序。Sun在Java中采用n层开发模型,并引入特定功能,允许更容易地开发服务器端可伸缩的、基于Web的企业级应用程序,从而在这个领域提供了Java自身所缺少的关键成分。

为什么要使用J2EE呢?它不是太新并且功能未经证实,它能提供什么?难道只是一种一时的技术狂热吗?在J2EE出现之前,JDBC API早已建立好了,可选用的轻量级的,可维护的servlet技术也已出现。除了这些,J2EE还提供了一些有前景的优点,它让开发人员关注开发业务逻辑,不用预先详细了解执行环境而把精力放到实现系统上,以及创建在硬件平台和操作系统(OS)间更容易衔接的系统。企业级软件开发是一项复杂的任务,需要具备许多不同领域的广泛知识。例如,一项典型的企业级应用程序开发工作可能要求你熟悉进程间的通信问题、安全问题、数据库特定访问查询等。

J2EE企业级开发平台鼓励在系统开发、部署和执行之间作一个清晰的划分。此开发人员可以将部署细节留给部署人员处理,如实际的数据库名称和存放位置、主机持有配置属性等。J2EE让系统可通过Java和J2EE而不是底层系统API被访问,从而支持硬件和OS无关性。由于这种原因,遵循J2EE体系结构技术规范的企业级系统可以非常容易地在硬件系统和不同的OS之间衔接。

在企业级开发领域,虽然面对Microsoft .net强大的挑战,但是J2EE由于上述优点,并且相对说来比较成熟,已经占据了企业级开发的大部分市场,并随着技术的进步、新的J2EE版本的发布、开源社区庞大自由开发者的支持,将会使企业级开发变得更高效,更快速,更高质量,更易于维护。

第一章 前言

J2EE核心技术有十三种,它们和J2EE API覆盖了企业级Java开发的广泛领域。在企业级Java开发工作中要用到的J2EE的方方面面知识是不太可能的。比较常用的有容器,servlet, JSP, EJB等。容器是一种运行在服务器上的软件实体,用于管理特定类型的组件。它为开发J2EE组件提供了执行环境。通过这些容器,J2EE体系结构就能在开发和部署间提供无关性,并在不同类型的中间层服务器间提供可移植性。servlet是一些可生成动态内容的Web组件。它们是当今在www上看到的最常用的J2EE组件之一。它们提供了一种有效的机制,用于基于服务器的业务逻辑和基于Web的客户端之间的交互,还可为通用的CGI脚本方法提供一种轻型且更易于管理的替代方法。JSP是另一种类型的J2EE Web组件,它是从servlet技术发展而来的。事实上,一部分JSP编译进servlet并在servlet容器中执行。EJB技术规范是J2EE平台的最核心的部分。它为构建可伸缩、分布式、基于服务器的企业级Java应用组件提供了一种综合性的组件模型。文章将结合这几种主要的组件技术来讲述构建J2EE系统的一般过程。

第二章 OOP的基本原则及发展方向

第一节 软件的可维护性与可复用性

    通常认为,一个易于维护的系统,就是复用率较高的系统;而一个复用较好的系统,就是一个易于维护的系统。也就是说一个系统的设计目标应该具有如下性质:可扩展性,灵活性,可插入性。

常听人说一个项目开发结束只完了这个项目的三分之一,可见系统的可维护的重要性。导致一个系统可维护性降低主要有四个原因:过于僵硬,过于脆弱,复用率低,黏度过高。通过良好的软件复用,可以提高软件的生产效率,控制生产成本,并能提高软件的质量,改善系统的可维护性,提高系统的灵活性和可插入性。

在面向对象的设计里,可维护性复用是以设计原则和设计模式为基础的,下一节介绍面向对象设计的基本原则。

第二节 六条OOP设计原则

OOP设计原则是提高软件系统的可维护性和可复用性的指导性原则,Java是一门纯面向对象的设计语言,因此我们在使用Java开发J2EE系统时必须遵守OOP设计的基本原则。

这些设计原则首先都是复用的原则,遵循这些设计原则可以有效地提高系统的复用性,同时提高系统的可维护性:

l        OCP开闭原则:一个软件实体应当对扩展开放,对修改关闭

l        LSP(里氏代换原则):它是继承复用的基石

l        DIP(依赖倒转原则):要依赖于抽象,不要依赖于具体

l        ISP(接口隔离原则):一个类对另一个类的依赖性应当是建立在最小接口上

l        CARP(合成/聚合复用原则):要尽量使用合成/聚合,尽量不要使用继承

l        LOD(迪米特法则):一个对象应该对其他对象有尽可能少的了解

    通过扩展已有的软件系统,可以提供新的行为,以满足对软件的新需求,使变化中的软件系统有一定的适应性和灵活性。而已有的软件模块,特别是最重要的抽象层模块不能再修改,这就使变化莫测中的软件系统有一定的稳定性和延续性。具有这些优点的软件系统是一个在高层次上实现了复用的系统,也是一个易于维护的系统。

里氏代换要求凡是基类型使用的地方,子类型一定适用,因此子类必须具备基类型的全部接口。

传统的过程性系统的设计办法倾向于使高层次的模块依赖于低层次的模块;抽象层次依赖于具体层次。抽象层次包含的是应用系统的商务逻辑和宏观的,对整个系统来说是重要的战略性决定,是必然性的体现;而具体层次则含有一些次要的与实现有关的算法和逻辑,以及战术性的决定,带有相当大的偶然性选择。具体层次的代码是会经常有变动的,不能避免出现错误。抽象层次依赖于具体层次,使许多具体层次的细节的算法变化立即影响到抽象层次的宏观商务逻辑,导致微观决定宏观,战术决定战略,偶然决定必然。从哲学意义上面讲这是很荒唐的事情,倒转原则就是要把这个错误的依赖关系倒转过来。

如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中的一个类需要调用另一个类的某一个方法的话,以可通过第三者转发这个调用。

   "针对接口编程"现在已经逐渐成为广大OOP程序员的共识,成为OOP设计思想的集中体现。一门语言即使不提供Interface这样的关键字,它也需要在很大程序上模拟出接口的功能。典型的如C++,通过声明一个只有纯虚函数的子类来模拟接口功能。不过这种模拟也就仅限于此,比如对于Java中的动态代理,抽象基类似乎就无能为力了。

OOP经过二十多年的发展,逐渐取代面向过程程序设计,已经相当成熟。OOP的设计思想主要体现在下以几个方面:

(1)   针对抽象编程,不针对具体编程。这是依赖倒转原则所要求的。换言之,应当针对抽象类编程,不要针对具体子类编程,这一原则点出了抽象类对代码利用的一个最重要的作用。

(2)   使用继承达到软件复用的目的。在Java中,继承有两种,一种是接口继承,一种是实现继承。第二种继承常常很容易被滥用。只要可能,尽量使用合成,而不要使用继承来达到复用的目的。

(3)   使用模板方式模式,它是类的行为模式,准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。

第三节 AOP的兴起

软件工程的发展史实际上就是抽象的发展史。随着软件越来越复杂,相应地我们也提高了编程语言的方法的抽象级别。因此,我们经历了从C到C++到Java,从结构化方法到面向对象的设计,从类到设计模型又到体系结构框架这一系列的改变,并且这个改变仍然在继续着。

AOP(Aspect Oriented Programming) 面向方面编程是一种超越OOP的编程模型,它允许程序员将横切关注点(散布在多个模块中的一致概念如同步处理,持久化,日志等都是典型的横切关注点)封装成清晰的可重用模块,然后通过组合这些模块和功能性组件获得系统的实现。AOP通过促进另一种模块性补充了OOP,便利我们可以很自然地处理一些传统的OOP不能解决的问题。

      在J2EE应用开发中,我们主要使用AOP的拦截(interception)能力,它提供了在任何对象的方法调用前/后加入自定义行为的能力。这使得我们可以处理企业应用中的横切关注点(同时作用于多个对象的关注点),并且仍然保持强类型,而不需要改变方法签名。例如,可以在一个应该具有事务的方法调用前开始一个事务,在方法返回时提交或者回滚。使用AOP可以把与事务管理相关的重复劳动放进一个框架内。

作为一个开发者,我每天大部分的时间面对的是数据库的存取,JNDI资源的访问,事情的声明释放,以及各处文件的读取等等,这些面对不同业务的同样操作。但是,在执行一步操作的时候往往我们需要配置一个比较完整的环境,如果JSP/Servlet容器,EJB容器等。在当今J2EE主流以发展轻量级构件的时代,我们有机会从摆脱这种重复的劳动,使用上轻量级的构件技术。

轻量级容器依靠反转控制(Inversion of Control. IoC)模式或依赖注入(Dependency Injection)现在是Java社区非常热门的话题,它实际上是针对接口编程这个OOP概念的进一步深化。利用IoC模式能够很好的解决代码调用者和被调用者之间的依赖关系,不仅可以灵活的装配我们的业务对象,更重要的是它让我们有机会在一个完整的环境中进行工作,使我们的业务开发不用再考虑环境因素。如果用得着某几项J2EE服务,就可以使用他们,比如,想用JTA就用JTA,想用数据库连接池就用连接池。这样,让我们的应用代码在J2EE环境下,不受任何运行环境的束缚。更有特色的是,轻量级容器借助AOP的横切服务甚至可以让我们的代码段中不包含try/catch这样的常用代码成例。因为这样这种异常处理是与环境相关的。

从概念上面来说,JNDI查找,事务,安全之类的基础设施都是与业务逻辑横切的。由于业务组件都是轻量级容器负责管理生命周期,使用者只要是通过容器进行组件访问,我们就应该让容器插入额外的代码来管理横切基础设施。然而,将这些基础设计进行外部声明,而不让他们进入到应用代码之中,才是一个系统实现可插入性的最好的实现办法。

在J2EE轻量级容器中,Spring无疑是最流行,发展得最好的,它提供的IoC容器不仅可以帮助我们完成我们的目标,而且它是开源的。

那么Spring如果将我们从重复的劳动中解放出来呢?一般,在我们写数据库接口时,需要访问数据库的时候都需要创建一个Connection,再声明一个statement,然后再进行具体的数据库操作,事务处理完闭之后,还要用try/catch语句将statement,connection close()掉。在JDBC2.0规范中,我们通常所做的方法是通过容器过(Tomcat5.0,Jboss,Weblogic都提供很好的JNDI支持)定义资源,并暴露为全局性的JNDI对象,这样,客户端的代码将直接通过JNDI访问这些资源,显然,应用代码将与JNDI基础设施绑定在了一起,也就是说应用代码与环境相关了,很难借助伪造的资源对象来进行单元测试,而且这些的代码既不易重用,也不能在J2EE环境以外运行。

没有评论: