CSDN博客

img xxcc

EJB设计模式(第二版)之EJB Command

发表于2002/7/8 9:48:00  1684人阅读

分类: Java

EJB Command

一个ejb客户端为了完成一个用例需要执行商业逻辑。

怎样让一个开发者用一个轻量级的态度实现一个用例的
商业逻辑,使客户端和ejb解耦并且用一个事务和一次
网络调用执行用例?

设计ejb系统时的一个重要的架构决定是把商业逻辑
放到什么地方?一个用例的商业逻辑是代表你的领域
模型中的合适的方法或跨多个其它entity bean 和/或
session bean执行逻辑(工作流逻辑)。

把商业逻辑放到客户端(servlet,applet,等等)有严重的
负面效果,影响性能和可维护性,如session facade
模式所解释的。问题可以被使用session facade模式
纠正,需要把商业逻辑放到session bean中,session
bean的每个方法映射到一个特定的工作单元,或者
用例。这样做,客户端被从服务器端的对象模型屏蔽
起来,并且在一个事务和一次网络调用的round trip中
执行用例。

session facade模式自己是ejb开发的关键,不过也有
它自己的缺点。直接从客户端调用session facade会导
致客户端和服务器之间的依赖(在一个大型项目和复杂的
客户端代码中),因为对EJB的紧耦合,如Business
Delegate模式所讨论的。这些问题能被用 business delegate
解决,增加一个封装所有对ejb层的存取的对象层。business
delegate能帮助让客户端代码简单,使客户端和服务器之间的
依赖最小。

然后session facade模式和business delegate模式一起提供了
使客户端从服务器端的实现细节解耦并允许在一个网络调用
和一个事务中执行用例的格式下写商业逻辑的最好的实践。
和通常一样,有trade-off:
1.更慢的开发过程。因为用例逻辑(经常会变化的)在一个
session bean中运行,任何时候一个用例需要改变(就是,
增加一个参数到一个方法或返回一个额外的属性),实现
那个用例的session bean方法可能需要修改。改变一个
session bean的过程不是可以忽略不计的----一个改变通常
需要编辑3个不同的文件(接口,bean class,deployment
descriptor)并且对ejb server的重发布和可能的重起服务器。
附加的,封装变化的session bean的在客户端的business
delegate将也需要修改。

2.大型项目中的劳动分工将更困难。依赖于一个项目中跨
开发者分配工作的策略,session facade是导致不同组或
开发者互相争斗的瓶颈,因为它将是随着项目进展时经常
变化的主题。

3.在一个大型公司中服务器资源经常被一个小组控制。
对一个有建立了的并且正在工作的发布的ejb集合的大型
公司,很难让其他项目的小组对已有的类施加影响和改变。

简单说,用session facade和business delegate开发会导致
长期的变化->发布->测试的round-trip,会成为大型项目的
瓶颈。问题的关键是商业逻辑放在一个session bean层,
几乎是重量级的开发。

综上所述:
  使用Command模式来封装商业逻辑到轻量级的command
bean,使客户端从EJB解耦,在一个网络调用中执行,作为
EJB层的一个facade。

一个command bean只是一个有get,set和一个execute方法的
普通Java类,和最初的command模式(四人帮(gof),1995)描述
的一样。应用到EJB,Command模式为了达到和session facade
和business delegate相同的好处提供了一个轻量级解决方案:
一个隐藏ejb层的对象模型,在一个事物和一次网络调用中执
行一个用例,完成使客户端从ejb解耦的facade。command模式
通过提供本地交互的类达到这一点,不过实际上在一个远程
ejb服务器上执行,对客户端透明。

Command被用来封装应用程序中的单独的工作单元。比如
placeOrder,transferFunds,等等的用例,将有它的商业/工作流
逻辑封装在只为那个用例的特定的Command,如图1.7所示。

和一个command交互的客户端十分简单。一旦一个客户端得到
一个command(创建一个或从一个factory得到,取决于实现),
它只是简单的对command设置属性,直到command包含所有需要
执行用例的数据。这时客户端能调用command的execute方法,
然后简单的执行command上的get直到得到所有command和用例
的结果数据。

当客户端执行command,有趣的事情在幕后发生。不是本地执行,
command实际上传输到一个远程ejb服务器并在ejb服务器的JVM
中执行。然而,所有的在执行用例的过程中被command调用的
ejb发生在ejb服务器上,一个用例能在一个事物中执行。这个
行为的实现机制晚些时候将在这个模式的讨论中讲解。

使用transfunds例子,一个客户端将设置用来取钱,存钱,传输
量的账号的ID。调用transfunds command的execute后,客户端
将得到最后账户的平衡,如1.8图所示。

可能Command模式最完善的实现之一是IBM的Command框架,和websphere
一同出现,是IBM为电子商务的模式的一部分。有很多实现ejb command
模式的方法,不过他们都有3个要素:

1.Command bean。一个有get,set和一个包含需要执行一个用例的商业逻辑
的execute方法的简单的java bean。command bean是应用程序开发者需要
写的command模式的唯一部分,下面所解释的其他组件是可以跨工程复用的。

2.客户端路由逻辑。通常负责执行命令(command)并把它发送到远程ejb
服务器的一个类的框架。这个路由逻辑通常对客户端不可见,通过调用
command的execute方法来触发。路由逻辑/框架是一个普通的能被跨工程
复用的类的集合。

3.远程Command server。Command server是简单的接受命令(commands)
并执行它们的服务。应用到ejb,command server类是一个接受命令(command)
作为参数并本地执行之的stateless session bean。Command server也是
普通的(generic)并且完全跨项目可复用。

客户端和这3个组件之间的交互如图1.9所示。在这个例子中,客户端调用
路由逻辑组件上的executeCommand方法。在IBM command框架中,客户端
只需要调用command自己的execute,因为方法调用将实际上被command的
超类接收到,它是路由逻辑框架的一部分。

在幕后,CommandExecutor代理了对一个ejb command目标(因为它是路由
逻辑的一部分,所以没有在图1.9中表示出来)的调用,它被编码成知道ejb
并且知道怎样发送命令(command)到command server stateless session
bean。通过接受命令(command),command server简单的调用command的
execute方法,command然后继续它的商业逻辑。

Command模式的好处如下:
1.因为轻量级的开发/分发过程,方便了RAD。
把一个用例写成Command bean比写成一个session
bean方法相对更容易和快速去分发和测试。经常
的变化能在一个普通java类上做,而不是一个
完全的EJB。

2.把商业逻辑从表示逻辑分离。Command通过封装
command内的商业逻辑来作为服务器上对象模型
的一个facade,只暴露一个简单的command接口
让客户端使用。这个分离让客户端和服务器分开
的演进。

3.强制用例在一个单独的round trip中执行。
因为command实际上在EJB服务器上执行,只需要
一次网络调用(和一个事务)来完成一个复杂的
用例。

4.使客户端从ejb解耦。客户端是完全的从服务器的
实现细节解耦的--所有它们能看见的只是command bean,
command bean看上去象是本地类。

5.命令(command)可以本地执行或产生哑(dummy)数据。
空的或虚的命令(command)能在项目开始前被创建,
允许表示层开发者去对于商业逻辑和ejb小组相对独立的
写,编译,和测试他们的代码。

很多方面command模式听起来像个终极的解决方案,综合了
session facade和business delegate的好处,和一个
轻量级的基础。然而,好处和通常一样,被重要的trade-off
所平衡:
1.非常粗粒度的事务控制。因为command只是普通java bean,
没有自动的标记一个command去在一个特定的事务设置或
isolation level下运行的方法,而你用session bean方法可以。
Command只能在执行它们的Command server的事务设置下运行。
这个的结果是用不同的jndi名字和事务设置(在deployment
descriptor中配置)来分发多个command server session bean。
路由逻辑组件需要被配置成发送特定的命令(command)到command
server。就是说,一种方法想发送只读command到没有事务的
session bean,然而更新命令能在command server下用tx_required
和可序列化的isolation level运行。

2.command是无状态的。command对象不能存储任何状态到执行它的
session bean中。用command模式在ejb层存储状态是不可能的。

3.笨拙的错误处理。因为command框架是通用的(generic),从
command只有CommandException能被抛出。这意味着,应用程序
异常,如NoMoneyAccountException,需要被捕获并用CommandException
封装。然后客户端需要为了特定的异常透视到command对象里面。因为
异常不是显式的宣称的,客户端失去了编译期检查异常处理的好处。

4.command在大型项目中会变得无法管理。用成千的command,
大型项目会爆炸的,很多command有重复的商业逻辑的部分,
特别当不同的项目小组使用同样的后端领域模型。这使得
维护商业逻辑层比起在session bean方法中实现用例的session
facade(很好的分组到数目很小的session bean中)困难得多。
这种类的激增将是大型项目的严重问题。

5.Command Server ejb-jar紧密的耦合到command bean和
其它ejb。因为command bean在command server的环境下
执行,为了使command bean反序列化和执行,command bean
类需要和command server session bean一起分发(在相同的
ejb-jar或EAR中)。这意味着只要command bean变化了,command
server session bean EAR或ejb-jar将需要重新分发(因此command
server classloader能读到所有包含的command的新版本),为了
测试变化,或完全重起(如果你的应用服务器不支持热分发)。
还有,command bean需要看见任何在它们的商业逻辑中使用到的
home,remote,local home,或local interface。这需要或者当
ejb被任何它们的command bean存取时command server分发到
相同的EAR,或者存取ejb的interface和command server的ejb-jar
打包到一起。

command模式和session facade模式一起提供了两个重要的好处:
他们作为一个facade和它们在一个网络round trip中执行。另一个
command模式比session facade模式好的主要优点是把客户端从
ejb解耦了,用business delegate和session facade一起也可以达
到。因此,开发者怎样从中选择呢?把command看作是更便宜(cheaper)
的session bean会有所帮助。它们是轻量级的,更快的先导开发过程,
以后来的差的可维护性作为代价。

相关模式
command(四人帮(gof),1995)
Data Transfer HashMap


0 0

相关博文

我的热门文章

img
取 消
img