/
by Dan Malks和Deepak Alur
June
在年的JavaOne大会上我们推出了《JEE核心模式》里面包含一个模式目录该模式目录中涉及了个JEE的设计模式这些模式是JEE平台下软件设计师和系统架构师经常遇到的典型问题及其解决方案这本书里面也列举了无数糟糕的实现并对它们进行了重构通过这些例子的学习你可以改善你现有的设计所有的这些模式都是在我们给客户创建成功的JEE应用过程中被发现并提炼出来的
模式与交流技术问题及其解决方案息息相关他们可以让我们记录一些反复出现的问题及其解决方案并与其他人进行交流写《JEE核心模式》的一个动力就是人们常把学习JEE技术与学习用JEE技术进行设计混淆起来现存的许多Java书籍大都介绍JEE技术的各个方面却几乎没有哪本书介绍如何应用这些技术基于作为Sun专家服务Java中心的Java系统架构师的经验我们觉得我们可以填补这个空白
不过那已经是过去了下面我们谈现在
《JEE核心模式》第一版出版以后我们收到读者对那个模式大量的反馈意见过去的几年中JEE模式讨论区非常活跃注册会员也超过人我们很高兴能从jeepatte收到大量读者的直接反馈意见这几年中我们又做了几个重要的大型JEE结构也参与几个项目的开发其间我们不断地应用这些模式同时又总结出了另外的一些模式
基于大家的反馈以及我们在工作中取得的经验在年的JavaOne大会上我们又推出该书的第二版原有的个模式全部都进行了修正和更新引进许多新的实现策略和例程增加了有关Web服务(Web service)的内容覆盖了最新的JEE我们又引进了个新的模式那么现在一共有个JEE设计模式新增加的个模式主旨在于改进模式语言提供了高度抽象你可以用来构造和理解JEE应用
模式目录
我们在第二版种引入了个新的模式每一层两个
表示层模式
环境对象(Context Object)
应用控制器(Application Controller )
业务层
应用服务(Application Service )
业务对象(Business Object )
集成层模式
域存储(Domain Store)
Web服务代理(Web Service Broker )
下面图中显示了模式目录中的个模式图图图分别显示了各层中的模式图显示了各个模式之间的关系请注意所有的模式都已经修正并更新过包括了一些新的实现策略以及一些新的例程
图 表示层模式
图 业务层模式
图 集成层模式
图 各模式之间的关系
精选模式
这一部分我们对新引进的个模式的一小部分进行一个简单的介绍其他更详细的信息包括其他模式实现策略例程UML框图糟糕的实现及JEE重构等请参考JEE核心模式
虽然直到现在环境对象(Context Object)才被记录为一个模式但是实际上我们在工作中会经常用到它环境对象(Context Object)的使用可以提高系统的的可复用性可维护性可扩展性以及易测试性下面我们介绍一下这个模式所涉及的问题解决方案UML类图UML序列图以及使用这个模式的后果
环境对象(Context Object)
问题
你想避免在相关环境之外使用与系统特定协议有关的信息
一个应用程序总是要通过请求/响应的生命周期使用一些系统信息比如请求信息配置信息以及安全性数据等这些系统信息总是与特定的处理环境有关如果应用程序的组件或服务在该特定环境之外直接使用这些系统信息的话那么这些组件的灵活性和复用性就降低了在特定环境的外部使用协议相关的API就意味着所有使用这些API的组件都被完全曝露了并且过于暴露了细节每一个客户组件因而都与特定的协议紧紧绑定在一起
解决方案
创建一个环境对象以一种与协议无关的方式封装系统信息然后在整个应用程序内部使用这个环境对象
如下面图所示把系统信息封装在一个环境对象中允许程序的其它部分共享访问这样就可以避免把应用同特定的协议绑定在一起比方说HTML form中每个域都是一个HTTP请求参数如果使用一个环境对象以一种与协议无关的方式存储这些数据的话那么数据的转换和验证就会变得容易一些而且程序的其它部分也可以直接从环境对象中访问这些信息不用考虑HTTP协议的问题如果协议发生变化了那么只用修改环境对象就行了应用程序的其它部分不用作任何改动
图 环境对象(Context Object)的UML类图
结果
提高了可复用性和可维护性
既然应用程序的接口独立于特定协议那么其中所定义的组件和子系统就更通用可以被各种各样的客户端复用
提高了易测试性
使用环境对象模式可以帮助清除与特定的Web容器或应用服务器相关的代码如果限制或者消除了这些依赖可以更容易进行测试比如说可以使用一些自动测试工具例如使用JUnit来进行自动测试
降低了接口变化的约束
原来应用程序的接口接受大量的系统信息现在使用环境对象封装这些数据应用程序只用接受环境对象就可以了这样可以降低应用程序与特定平台的耦合度使得以后的修改可以更容易进行这对于开发应用程序框架非常重要当然对于开发通用程序也很有价值
性能的降低
使用环境对象模式要在对象间传递各种数据因而会导致一定程度性能的下降不过性能的些微下降与使用环境对象带来的好处比如应用程序组件复用性提高应用更容易维护和修改等等比起来实在是微不足道
我们在业务层模式中新增加了两个模式其中之一就是应用服务(Application Service)这个模式与普通的业务逻辑有关因为如果使用Session Façades的话就会导致代码重复而如果把这些逻辑封装在业务对象(Business Object)的话又会导致对象数量的剧增
应用服务(Application Service)
问题
你想跨越几个业务层组件和服务通过聚合来形成一个业务逻辑
服务门面(Service facade)像Session Façade或者POJO Façade几乎不包含业务逻辑只是对外提供了一个简单的粗糙的接口业务对象(Business Object)封装了一组相关业务操作的行为用例(Use Case)用来协调这些业务对象和服务而应用程序则用来实现这些用例然而你不应该让用例协调业务对象(Business Object)内部的行为这样会增加依耦合性降低这些业务对象间的内聚力同样你也不应该把业务逻辑加到服务门面(Service facade)上因为业务逻辑在不同的门面之间潜在地复制了代码这样会降低通用代码的复用性和可维护性
解决方案
使用一个应用服务(Application Service)聚合各种行为来提供一个统一的服务层
应用服务(Application Service)提供了一个实现业务逻辑的中心位置这个业务逻辑可能封装了各种业务对象和服务这种实现业务逻辑的方式可以降低业务对象间的耦合性使用应用服务(Application Service)模式你可以把分散的使用底层业务对象和服务的组件封装成为一个高级的业务逻辑
即使你的应用程序中没有用到业务对象(Business Object)你也可以使用业务服务(Application Service)模式来提供一个统一的业务逻辑实现层这种情况下应用服务(Application Service)可能会包含你程序中实现不同服务必需的所有中间业务逻辑如果要处理持久性数据的时候可能还会包括数据访问对象(Data Access ObjectDAO)
图 应用服务(Application Service)