一、概述
许多实际开发软件的人都没有时间始终跟踪注重有哪些关于设计和体系结构的言谈,即使他们有时间,他们也是希望从中找出一些具体的应用以帮助他们在下一次焉设计系统的时候可以做出更明智的选择。型式(pattern)是一个良好的体系结构和设计信息来源,可以练习软件设计者。
在许多专业水平的规则中,有一条要害的规则是不要低水平的重复。目前设计领域的一些实际情况,也就是一项设计大部分是在相关上下文环境中已有理想应用的综合。没有一个软件设计师采用的是全新的一套思想来生成软件系统;要害是把这些知识都汇集起来,以便于所有软件设计师都可以生成更好的系统。来自Sun公司的Bill Joy的说法,表明并不是所有良好的思想都来自Sun公司内部,因此人们必须对其他领域打开自己的思想。幸运的是,软件开发者越来越注重分享他们的思想,在开放源代码(Open Source) 社团中,人们还共享代码。这种在代码和思想上合作的趋势促成了软件设计型式(pattern)目录的产生,这些内容可供公共使用,并且可以帮助人们设计各种不同的软件系统。
一个型式就是在一种给定上下文环境下已经证实的解决方案。具体环境越宽,对应的型式适用的面就越广。在软件术语中,型式实际上指人们在实践中获得的“经验总结”,指出在指定、设计和实现软件系统时哪些工作效果最好。
在许多软件和系统领域都可以找到型式。在高层,人们在执行特定领域的分析时可以找到型式。在这种分析中发现的实体和关系将在一个业务方面反复出现。这种重复性使人们发现了相应的型式。假如你在某个特定领域工作,如金融或者电信,则调查一下现有的具体领域的型式可以节省时间和精力。型式也可以是某种特定技术或者语言专用的(有时称为“惯用语”)。java专用的型式在语言惯用语的各级中都存在。
二、J2EE型式的应用
对于J2EE型式,可能对此最突出的体现就是由Sun Java Center的一些Java设计师所做的工作。他们已经根据Sun公司PRofessional Services(专业服务)人员多年基于J2EE的实际系统实现生成了一组专门用于J2EE的型式。这组型式位于在线的Java Developer Connection(Java开发者连接)中,并且正在通过J2EE Patterns电子邮件群发展和变化。
Sun Java Center的J2EE型式针对的就是n层业务系统,并且根据驻留的层而分类为:Presentation、Business和Integradon。下表1显示了此分类中的一些更常见的示例型式。
这个列表只是Sun Java Center中提供的J2EE型式的一部分,J2EE型式也是J2EE Blueprints 的组成部分。提供的这些型式实例经过证实都可以在J2EE系统平台上工作,这是对设计者的极大帮助。我们可以从别人的经验中学习,并且观察他们如何为自己的环境实现相关的型式。 我们不能只使用J2EE专用的型式或者其他任何型式,它们就像一堆积木,简单地复制和粘贴这些代码形成自己的解决方案而不更改任何代码是不好的。有经验的设计师将把一个型式作为一个总体指导使用,让它符合特定上下文环境的需要。
所有的应用程序上下文环境都有一定程度的惟一性,因此这些型式的实现必须经过调整以满足我们特定的要求。同时,一组型式肯定无法覆盖我们整个应用程序的要求。我们应该把型式看作为一组“设计时使用的”组件,可以经过调整然后通过自定义的逻辑结合起来(它本身是可以调整的)而得到最终的产品。
表1 J2EE型式应用
1、前端控制器型式
为用户生成显示的视图应该包含最少的业务代码,以便于在多个视图中共享以及可以独立于具体的视图而更改。这些规律也适用于为视图提供普通服务的代码以及在视图之间提供工作流和导航的代码。普通服务如安全性和状态治理,不应在多个视图之间复制,因为这样会带来系统维护方面的问题和一致性问题。与一个应用程序的某部分关联的工作流,如进行一个在线购物的一系列步骤,当控制其相关导航的代码分在多个视图中的时候将更难被改变。
Front Controller(前端控制器)型式引入了一个组件,它捕捉客户请求并且进行下列一项或者多项处理:
●应用普通服务,如验证和访问控制。
●决定处理请求的适当视图。
●通过处理用户令牌和访问的数据源为相关请求建立状态信息。
图1显示了一个前端控制器如何实现一个客户和多个视图之间的中介。这种中介可能是应用程序中一个工作流的一部分,也可以是在语言或者其他因素基础上的一个选择。
图1
一个前端控制器可以与其他组件或者帮助器(helper)交互以提供要求的服务。前端控制器使用一个分离的分配器组件来实现要求的任何工作流也是常见的情况。它还将使用帮助器(如View Helper即视图帮助器型式)来执行与业务有关的处理或者把状态信息传递给视图。图2所示的情况说明了这些组件之间的交互。
图2
2、复合视图型式
大多数基于Web的系统由许多不同的网页或者视图构成。每个视图都将包括一些专用的功能,如同时可供选择的部分产品列表,以及普通的导航、信息或者功能化元素。假如对于这些元素的代码和格式在多个使用它的视图中都重复,则系统会非常难于更新和维护,因为任何修复和更改都必须在相关代码和格式处理出现的地方应用。
作为一种解决办法,复合视图(Composite View)型式定义了各种阶段以有效地把一个用户的接口划分成多个子视图,并且可以被重新结合起来以生成需要的总体视图。每个子视图构成一个单独的组件,可以与其他子视图分开维护、更新和增强。构成复合视图型式的一个示例Web网页。在这里我们设计在屏幕顶部有一个Header View(标题视图),在这个标题下方和网页的左侧有导航视图,当然还有居中显示的Main Body(正文)视图。复合视图的总体构成可以使用图3所示的其他视图。
图3
视图治理器可以包含在复合视图和子视图之间。一个视图治理器的使用是可选的,但假如要求有条件地包含一些内容,则它会有用。作为一个jsp网页实现而不包含一个视图治理器的简单复合视图实现,如下:
<table border="0" valign="top" width="100%"
<tr
<td<jsp:include page="templates/header.jsp"/</td
</tr
<tr
<td<jsp:include page="tenlolates/navigation.jsp"/</td
</tr
<tr
<td<jsp:include page="content/java_book_list.jsp"</td
</tr
</table
3、会话正面型式
假如EJB简单地用作业务数据的存储或者简单的业务服务,那么大多数业务逻辑都将仍然驻留在使用这些BJB的客户上。这样做是有害的,原因有两方面。首先,它将再次带来过量的网络访问,因为客户要访问很具体筛选的业务服务和数据。它还会把客户强烈地联系在业务处理中。这样在客户之间造成了不必要的业务代码分散和重复。
解决的办法是采用正面(Facade)型式的一种变形,正面(Facade)是指一个对象或者组件,它被引入到客户和一个复杂的子系统之间。这个正面只展示客户要求的服务以及相关的综合服务,这样可以提供粗选的相应服务(不是细选)。在J2EE型式术语中,会话正面(session Facade)为业务逻辑和多个EJB封装的服务执行这个角色。会话正面,如其名字所示,采取的是一个会活EJB的形式。客户与会话正面通信,会话正面再根据其他EJB如实体bean来提供业务服务。
图4显示了一个会话正面如何控制对多个实体bean的访问并且提供一个对客户统一的接口。会话正面虽然一般用作基层实体EJB的一层掩护,但一个会话正面既可以从其他会话EJB访问服务和数据,也可以从数据访问对象(Data access Objects)来访问。这些类之间的关系如图4所示。
图4
通常,会话正面会为一个或者多个业务使用案例封装相关功能。通过对该正面的一次调用可以得到多个业务操作(这种情况有时称为批处理方法分布式型式/惯用语)。客户想要执行的操作不是在返回一组值对象(Value Objects)的一个会话bean上的操作,而是可以移植到会话正面中。接着发生的是在服务器上迭代处理数据,只把结果传送回客户。这样就减少了网络传输量,当然也给服务器处理带来了一些负担。
4、服务定位器型式
从代码中看,在一个EJB的业务接口上使用方法带来的负担相对较小,只需要处理远程异常而已。但是EJB的生成需要有专门的基于JNDI的代码来发现主接口并且生成需要的EJB。这就迫使客户要包含相关代码以处理上下文环境的牛成、查找并且缩小引用的范围。同时,任何其他的复杂化如主接口引用的缓冲存储,必须被每个客户重复。
服务定位器(Service Locator)型式定义了一个对象可以如何执行与多个客户关联的多个EJB的查找和生成任务。客户只是简单地找到服务定位器,并且请求对需要的EJB的一个引用。所有与JN