模式与J2EE


blueski推荐 [2005-3-24]
出处:来自网上
作者:不详
 

信息工程是以当前数据系统为基础,在一个企业或企业的主要部门,关于建设信息系统的规 划、分析、设计和构成的一整套相互关联的正规化、自动化的技术应用。

--- 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等人的<J2EE核心模式,2001>等,其中最具影响的是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有关的模式。具体模式可参看下面表格:

表一:表示层模式
模式名 简单描述
截取过滤器(Intercepting Filter) 促进请求的预先处理和后处理
前端控制器(Front Controller) 提供请求处理的集中控制器
视图助手(View Helper) 把与表示层格式化无关的逻辑封装到助手组件
复合视图(Composite View) 从原子的子组件创建一个聚集视图
工作者服务(Service To Worker) 合并分发者组件、前端控制器和视图助手模式
分发者视图(Dispatcher View) 合并分发者组件、前端控制器和视图助手模式,把许多动作推迟到视图处理


表二:业务层模式
模式名 简单描述
业务委托(Business Delegate) 把表示层和服务层分隔开,并且提供服务的外观和代理接口
值对象(Value Object) 通过减少网络对话,以加速层之间的数据交换
会话外观(Session Facade) 隐藏业务对象复性,集中化工作流处理
复合实体(Composite Entity) 通过把参数相关的对象分组进单个实体bean,表示设计粗粒度实体bean的最好经验
值对象组装器(Value Object Assembler) 把来自多个数据源的值对象组装成一个复合值对象
值列表处理器(Value List Handler) 管理查询执行、结果缓冲、以及结果处理
服务定位器(Service Locator) 封装业务服务查找和创建的复杂性,定位业务服务工厂


表三:集成层模式
模式名 简单描述
数据访问对象(Data Access Object) 抽象数据源,提供对数据的透明访问
服务激发器(Service Activator) 加速EJB组件的异步处理

    由于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对象代码维护会带来负面的影响。下面图4为运用分离数据访问对象方法对其进行重构改进后的结果。



    在15个J2EE模式中,每个模式都作用于设计模式和构架模式之间的某些方面。每个模式不是孤立存在的,需要其它模式的支持才能更加体现其含义和用处,为了最大限度的用好模式,还需要充分理解模式之间的关系。

参考文献

 

  • 系统分析员教程 --- 罗晓沛等箸
  • 设计模式:可复用面向对象软件的元素 --- 李英军等译
  • 重构-改善既有代码的设计 --- 侯捷等译
  • J2EE核心模式 --- 牛志奇等译
  • UML精粹(第二版) --- 徐家福译