摘要:
现今大多项目从小型开始发展并成为大型的可升级的体系结构,但是,当体系改变时,相应的商业逻辑实现也要改变。用户接口可能不需要改变,但是为了可测量,商业逻辑必须从单纯的JavaBean实现过渡到用Enterprise JavaBeans (EJB)来实现。如果现在的应用程序没有被设计成适应商业逻辑实现的改变,大多数用户的界面代码需要更新以使用商业逻辑服务。在本篇文章,使用一个简单的框架来访问业务对象,你将会学到如果构架你的应用程序以使业务对象改变时不需要改变用户接口。
By James Carman
许多架构师努力减小在多应用中存在的表示层和业务逻辑层之间的耦合度,业务代表(Business Delegate)设计模式可以来解决这个问题,但许多评论指出这是画蛇添足。业务代表接口模仿业务逻辑接口如此紧凑以至于任何对业务逻辑的改动都会导致业务代表接口的变动,这一话题一直有争议。多数情况下是这样子,但业务代表模式有它的优点,比如:远程隐藏,错误恢复,线程同步和缓冲。但许多应用业务代表模式的应用程序并不利用这些额外优点,这样就有点大才小用了。这些应用程序所需的是一种隐藏了底层实现细节的提取层,比如我们熟悉的lookup和narrow操作需要由EJB来实现。这篇文章将引领你来贯穿学习API,配置还有业务对象工厂框架的实现。
注意:你可以从此处下载本篇文章附带的源码Resources.
THE API
业务对象工厂框架最简单的部分就是他的API本身,仅有一个主类,并有一些其他的后台的类可以扩展和定制这一框架。
The BusinessObjectFactory class
除了在程序中使用的业务接口,业务对象服务的使用者只需关注一个主类BusinessObjectFactory,下面来看这个接口:
public final class BusinessObjectFactory
{
public BusinessObjectFactory getInstace();
public Remote create( Class businessInterface );
}
正如你所见,BusinessObjectFactory类实现了一个单一设计模式,他的构造函数声明为私有,并且该类只持有一个静态实例,这样就使得BusinessObjectFactory类只提供一个全局功能入口点,我们也可以仅仅把所有方法设为静态的,但前者更有导向性。
首先,create()方法返回java.rmi.Remote的一个实例,大多数业务对象实现上有选择,也就是RMI,EJB以关于基于XML的远程调用(JAX-RPC)的API,需要一个远程接口。简单的基于JavaBean的业务对象的实现,客户端代码时刻需要捕获java.rmi.RemoteException异常,这就带来了些不便。但是,这种不便提供了实现上的透明性,也就是不改变客户端代码就可以使业务对象能被改换成不同的方法来实现,唯一的约束就是远程就口不能被改变。create()方法的另一特性就是他的参数类型,java.lang.Class,这符合远程接口类型,用它可以使得BusinessObjectFactory类轻松的被加到应用程序里。这并不阻碍XYZ使用创建的适配类来简化客户端程序:
public class XyzBusinessObjectFactory
{
// Reference to singleton used for brevity, not required!
private BusinessObjectFactory bof = BusinessObjectFactory.getInstance();
public AccountServices createAccountServices()
{
return ( AccountServices )bof.create( AccountServices.class );
}
}
在上述代码中,当使用BusinessObjectFactory类时类XyzBusinessObjectFactory可以包装所需的型别转换,使得客户端代码更简洁和型别安全。
我们要注意BusinessObjectFactory类的方法并没有抛出直接继承自java.lang.Exception类的异常,有问题的话会在执行时抛出运行期异常(runtime exceptions),这些问题出现在配置上而不是程序本身。由于运行期异常并不需要try/catch块,这样就极大的简化了客户端代码,但也要根据需要允许捕获定制的异常。在一个WEB应用里,可以在web.xml定义一个servlet过滤器或者是一个自制的错误提示页面来捕获这些异常。JDO API就采用这样的机制。
另外关于类BusinessObjectFactory要注意的是它被声明为final类型,这样使得使用抽象工厂工厂方法设计模式在隐藏实现框架中变得更为典型,例如DAO(Data Access Object)设计模式。但如你所见,业务对象框架的扩展性并不由子集而是需要委托来实现。
类BusinessObjectFactoryDelegate
类BusinessObjectFactory产生BusinessObjectFactoryDelegate的一个实例作为委托代表:
public abstract class BusinessObjectFactoryDelegate
{
protected abstract Remote doCreate();
public final void setBusinessInterface( Class businessInterface );
public final Class getBusinessInterface();
}
类BusinessObjectFactory实例创建一个实现了远程业务接口的业务对象实例,并被businessInterface属性重新描述。你可以尝尝实现BusinessObjectFactoryDelegate的不同滋味,每种都会描述其他一些业务
对象的实现途径,例如JavaBeans, RMI, EJB, or JAX-RPC.稍后我会举些例子。还需要注意客户端代码并不需要暴露给任何BusinessObjectFactoryDelegate实例,我们将会看见BusinessObjectFactory类可以内在地关注所有的委托,这并不是该框架唯一隐藏的特性。
InvocationDecorator接口
客户端代码有时候会使用业务对象框架的另一格式,即使它对此并不了解。InvocationDecorator接口代码如下:
public interface InvocationDecorator
{
public Object decorate( Method method, Object[] args, InvocationDecoratorChain chain ) throws Throwable;
}
InvocationDecorator实例有机会截取每个方法的映射并加以修饰,一些潜在的修饰操作,比如:日志,事务处理及授权。每一个InvocationDecorator实例可以执行一些操作,并作为一个参数传递给InvocationDecoratorChain的实例。如下:
public interface InvocationDecoratorChain
{
public Object decorate( Method method, Object[] args ) throws Throwable;
}
InvocationDecoratorChain的对象持有经排序过的InvocationDecorator的实例,并最终调用相关的业务对象所需的方法。对于那些熟悉JAVA servlet API的来说,这就像是servlet2.3规范中的servlet过滤器。实际上该思想也是借鉴于此规范,当我设计该框架某部分时得到的一个念头。为什么不用AOP(ASPect-oriented programming)和AspectJ来修饰每个映射呢?因为,改变你的代码的话AOP需要重新编译,而InvocationDecorator实例在InvocationDecoratorChain里增加或删除的话只需要改一下配置文件就可以了。
matrix开源技术经javaworld授权翻译并发布.
如果你对此文章有任何看法或建议,请到Matrix论坛发表您的意见.
注明: 如果对matrix的翻译文章系列感兴趣,请点击oreilly和javaworld文章翻译计划查看详细情况
您也可以点击-javenmen查看翻译作者的详细信息.进入讨论组讨论。
(出处:http://www.knowsky.com)