概要
值对象是一些单一的参数,用来联合一系列的对象——在大多数的情况下,在一个方法调用里有各种各样的参数。这些参数描述了一个大数量级的属性,通常,这些属性需要单独检测,而且大多数情况下是检测其是否为null。通常,这些检测带出来了大量的代码行。这篇文章描述了如何实现基于著名的Visitor模式和反射的值对象。
在业务过程中,你通常有一些属性不能为空,而另外一些则没有这样的要求。在那些必须有实例的属性的案例中,你不得不实现如下所示的检测:
if( attribute1 == null )
{
throw new Attribute1IsNullException()
}
如果值对象有N个属性,你将会得到如下所示的代码:
if( attribute1 == null )
{
throw new Attribute1IsNullException()
}
if( attribute2 == null )
{
throw new Attribute2IsNullException()
}
...
if( attribute N == null )
{
throw new AttributeNIsNullException()
}
结果:一大堆的IF语句,但是你不得不把它们全部打出来。
现在假设校验的数量从10增加到25,因为有15个新增的用例必须在一个循环中实现。你是不是失去了勇气?用来减少这些检测的一个有效的方法是将他们从值对象类移到值对象的校验类。
从这个观点看来,你可能承认你永远执行相同的检测。唯一的不同是属性的名称和类型。在大多数情况下,类型不让人感兴趣,因为由编译器检测它。还有重要的一点需要确认:接收这些属性的值的方法都由同一个名称开始,在我们的案例中,是get。
通过反射调用这些值对象的getters方法非常简单。如果你使用Eclipse,例如,你可以自动为所有的属性产品setters和getters方法。对于我们的attribute1,getter方法是getAttribute1(),setter方法为setAttribute1(Integer attributeValue)。如果attribute1是Integer类型的属性。如果这些前提给定了的话,你就能考虑一个一般的解决方案。这篇文章解释了如何使用Visitor模式和反射来实现这个一般的解决方案。
框架类和接口
下面的类图显示了建立我们一般的校验框架需要用到的类和接口之间的关系:
注意:你可以从Resources上下载这些类和接口
查看本文来源