知识大全 校验值对象——应用Visitor模式和反射

Posted 属性

篇首语:少年意气强不羁,虎胁插翼白日飞。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 校验值对象——应用Visitor模式和反射相关的知识,希望对你有一定的参考价值。

校验值对象——应用Visitor模式和反射  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

概要 值对象是一些单一的参数 用来联合一系列的对象——在大多数的情况下 在一个方法调用里有各种各样的参数 这些参数描述了一个大数量级的属性 通常 这些属性需要单独检测 而且大多数情况下是检测其是否为null 通常 这些检测带出来了大量的代码行 这篇文章描述了如何实现基于著名的Visitor模式和反射的值对象   在业务过程中 你通常有一些属性不能为空 而另外一些则没有这样的要求 在那些必须有实例的属性的案例中 你不得不实现如下所示的检测 if( attribute == null )     throw new Attribute IsNullException() 如果值对象有N个属性 你将会得到如下所示的代码 if( attribute == null )      throw new Attribute IsNullException()if( attribute == null )      throw new Attribute IsNullException() if( attribute N == null )      throw new AttributeNIsNullException() 结果 一大堆的IF语句 但是你不得不把它们全部打出来 现在假设校验的数量从 增加到 因为有 个新增的用例必须在一个循环中实现 你是不是失去了勇气?用来减少这些检测的一个有效的方法是将他们从值对象类移到值对象的校验类 从这个观点看来 你可能承认你永远执行相同的检测 唯一的不同是属性的名称和类型 在大多数情况下 类型不让人感兴趣 因为由编译器检测它 还有重要的一点需要确认 接收这些属性的值的方法都由同一个名称开始 在我们的案例中 是get 通过反射调用这些值对象的getters方法非常简单 如果你使用Eclipse 例如 你可以自动为所有的属性产品setters和getters方法 对于我们的attribute getter方法是getAttribute () setter方法为setAttribute (Integer attributeValue) 如果attribute 是Integer类型的属性 如果这些前提给定了的话 你就能考虑一个一般的解决方案 这篇文章解释了如何使用Visitor模式和反射来实现这个一般的解决方案   框架类和接口 下面的类图显示了建立我们一般的校验框架需要用到的类和接口之间的关系 注意 你可以从Resources上下载这些类和接口   Validateable接口 Validateable接口有着和Visitable接口相同的功能 那个定义的方法validateWith()是一个和Visitor模式里的Visitable接口的accept()方法相似的方法 通过validateWith()方法 你就能够校验有着不同validators的值对象 因为这个方法以IClassAttributeValidator接口的实现作为参数   IClassAttributeValidator接口 IClassAttributeValidator接口和Visitor模式的Visitor接口相对应 其中的validate(AbstractParameter param)方法和Visitor接口的visit(object SomeObject)方法相似 validate()方法的AbstractParameter参数类型允许我们通过任何AbstractParameter类的子类类型的参数访问validate 另外 在validateWith()方法里使用这个接口作为参数允许我们在将来改变使用的validator 用这些改变的validator作为来满足不同的validation的需求——例如 除了null检测以外 在一个定义的值范围测试参数属性   AbstractParameter AbstractParameter类实现了Validateable接口的validateWith()方法 就像你将要看到的下面的代码片断一样 这个实现非常简单 这个方法仅仅是调用给定的validator的validate()方法 并且传递参数对象到validator public void validateWith( IClassAttributeValidator validator ) throws Exception       validator validate( this ); 而且 AbstractParameter也实现一些常用的其他方法 受保护的方法 addOptionalMethod()使得所有的子类型增加一些可选择的方法到optionalGetAttributeMethods HashMap() 继承自AbstractParameter使得你能够取得哪些可能传递null的getters方法 就像你能想象到的一样 你能够增加可选择的方法 例如 到继承自AbstractParameter的值对象的构造器里 isOptionalMethod()方法用于检测属性是否已经被校验过了 toString()方法实现了一些便利 因为值对象可能是由很多属性组成 使得在AbstractParameter的子类里 不需要写很多的System out printlns实现 这个方法也是使用反射达到目的的   GenericClassAttributeValidator GenericClassAttributeValidator类实现了IClassAttributeValidator接口的validate()方法 这个类同时也实现了单态模式 validate()的实现看起来象下面这样 public synchronized void validate( AbstractParameter param ) throws AttributeValidatorException      Class clazz = param getClass();      Method[] methods = clazz getMethods();      //Cycle over all methods and call the getters!      //Check if the getter result is null       //If result is null throw AttributeValidatorException       Iterator methodIter = Arrays asList( methods erator();      Method method = null;      String methodName = null;      while ( methodIter hasNext() )                  method = (Method) methodIter next();            methodName = method getName();            if ( methodName startsWith( get ) &&            clazz equals( method getDeclaringClass() ) &&                 !param isOptionalMethod( methodName ) )                             Object methodResult = null;                 try                                        methodResult = method invoke( param null );                                  catch ( IllegalArgumentException e )                                        throw new AttributeValidatorException( e getMessage() );                                  catch ( IllegalAccessException e )                                        throw new AttributeValidatorException( e getMessage() );                                  catch ( InvocationTargetException e )                                         throw new AttributeValidatorException( e getMessage() );                                  if ( methodResult == null )                                        String attributeName = methodName substring( ) toLowerCase() +                       methodName substring( methodName length() );                       String className = clazz getName();                       className = className substring( className lastIndexOf( ) + );                       Integer errorNumber = new Integer( );                       throw new AttributeValidatorException( Error: + errorNumber +                        + attributeName + in + className + is null!!! );                                   首先 就像你在代码里看到的那样 我们从值对象里取得所有的方法 然后 我们遍历所有方法的集合 如果方法以get开头 便是AbstractParameter的子类型 而不是可选择的方法 我们通过反射调用getter方法 并且检测它的结果 如果结果是null 那么这就是一个错误 如果不是 便是正常情况 那些可选择的方法和继承自父类的方法不会被执行   测试我们的类 现在 我们实现了我们所需要的所有的类和接口 我们必须做一些测试来检验我们的类是否能够正常工作 为了做到这一点 我们写了一点小的测试类和一个main方法来运行测试   TestParameter TestParameter类继承自AbstractParameter 并且包括了一些需要校验的私有属性 很简单的 个Integer属性   Optional attributes 为了识别可选的属性没有被检测 我们定义了为属性 testParam 可选的getter方法 为了这个目的 我们通过TestParameter的构造器里的addOptionalMethod(methodName)方法将这个getter方法输入到父类AbstractParameter的可选方法map里   校验框架是如何工作的 为了测试 我们在TestParameter里使用如下方式输入 TestParameter param = new TestParameter( );param setTestParam ( new Integer( ) );param setTestParam ( new Integer( ) );param setTestParam ( new Integer( ) );param setTestParam ( new Integer( ) ); 就像你所看到的那样 个Integer属性记作Integer 和 为了校验 我们仅仅调用 param validateWith( GenericClassAttributeValidator getInstance( ) ); 这个校验的结果是 testParam : testParam : testParam : testParam 属性没有被校验 因为我们记录了它的getter方法为可选的 其他所有的方法得到了校验 并且结果是正常的 现在 我们希望看到其中的一个属性值为空 这样我们就能检测是否validator能够检测到这个错误 我们注释掉下面的行 param setTestParam ( new Integer( ) ); 我们重新开始测试以后 得到如下的结果 testParam : Error: testParam in TestParameter is null!!!testParam : 现在我们看到了validator已经检测到了这个没有赋值的属性   如果属性类型为集合类型 将会怎么样呢? 如果属性类型为集合 它仍然会检测这个集合是否为空 但是 可能检测集合是否为null并不是你想要的 在大多数情况下 你希望检测集合里的对象是否为null 如果集合的实现不允许null对象 你不需要关心这些在GenericClassAttributeValidator里的null对象继承自AbstractParameter 一些为集合保持继承自AbstractParameter的对象的辅助代码看起来如下所示 if ( methodResult instanceof Collection )      Collection col = (Collection) methodResult;      Iterator iter = erator();      Object subParam = null;      while ( iter hasNext() )                  subParam = iter next();            if ( subParam instanceof AbstractParameter )                             AbstractParameter abstractParam = ( AbstractParameter ) subParam;                 abstractParam validateWith( this );                  集合里的所有没有继承自AbstractParameter类的对象没有被检测 因为我们将使用一个不允许null对象的集合实现 所以集合实现为我们完成了检测 如果你决定使用一个允许null对象的实现 那么为while循环的所有其他的对象的一个额外的null检测就是必须的了 else if( subParam == null )      System out println( Error: SubParameter not set in Collection! );   值之间的依赖 在一些情况下 只有当值对象的其他属性被分配了值 一个属性才有可能是可选的 属性的 可选性 sometimesOptional依赖于actionType属性的值 可能action属性持有的值代表了actions 例如addSomething = updateSomething = 和 deleteSomthing = 如果action的值是 或者 sometimesOptional属性不是可选的 如果action的值是 则是可选的 当我们为actionType赋值的时候 我们必须设置sometimesOptional的可选性 public void setActionType(int actionType)      this actionType = actionType;      super clearOptionalMethods( );      switch( this actionType )                  case ActionParameter ACTION_ADD :            super addOptionalMethod( getSometimesOptional );            super addOptionalMethod( getSometimesOptional );            break;            case ActionParameter ACTION_UPDATE :            super addOptionalMethod( getSometimesOptional );            break;            case ActionParameter ACTION_REMOVE :            super addOptionalMethod( getSometimesOptional );            super addOptionalMethod( getSometimesOptional );            super addOptionalMethod( getSometimesOptional );            break;            default :            break;      你会看到清除可选方法列表是必需的 因为如果你给actionType赋值超过一次的话 越来越多的方法将作为可选的方法添加进来 另外的一个解决方法包括实现一个AddActionParameter 一个UpdateActionParameter和一个RemoveActionParameter 它们都是从AbstractParameter类继承得来 那么你可能不需要actionType属性 但是拥有actionType属性的类存在并且经常被使用 对该类使用反射非常容易 你必须使用Switch语句   展望 现在 我们可以考虑继承AbstractParameter的更多的功能——例如 范围校验 AbstractParamter需要一个数据结构来存储范围值 HashMap能够做到 它以方法名作为key存储范围对象 或者你可以检测是否一个String类型的值包含一些定义的字 等等 你也可以考虑Perl 的正则表达式 所有的这些检测都可以在Validator类里实现 它实现了IClassAttributeValidator接口 如果你想使用属性的null检测和附加值检测 那么你可以写一个子类来继承GenericClassAttributeValidator 在J EE应用里 值对象经常被用来在客户端和服务器之间传递业务过程的数据 但是 如果你仅仅在服务器端校验这些值对象的属性 你常常不得不因为一个错误的非可选属性为null而取消业务过程 你必须中断业务过程 而向客户端发送一个错误页面 这是一个好的实践 在服务端应用这些validators的同时 你也可以以委派的形式在客户端应用它们 在客户端检测值对象可以避免不必要的对服务器的请求和降低网络堵塞   写一次 使用多次 如果你使用我描述的方法来检测你的值对象的属性 你可以永远只增加值对象的属性——不用改变validator 它们能够被自动检测是否为null 你也可以不用改变validator而改变一个属性的条件 而且 当然 一个已有的validator也能够校验一个未来的值对象 如果这个值对象继承AbstractParameter的话 还有 你也可以不用改变值对象而写一个额外的validators 因为validators实现的是Visitor模式 这就是所谓的写一次 使用多次 cha138/Article/program/Java/gj/201311/27352

相关参考

知识大全 关于Struts2中visitor校验器的解决方法

关于Struts2中visitor校验器的解决方法  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 

知识大全 java设计模式之Visitor

java设计模式之Visitor  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Visitor定

知识大全 Java设计模式-----Visitor访问者模式

Java设计模式-----Visitor访问者模式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 

知识大全 在组合模式中实现访问者(Visitor)模式

在组合模式中实现访问者(Visitor)模式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  本文

热电阻元件有几种校验方法?

  热电阻元件一般有两种校验方法:  (1)分度校验法:即在不同温度点上材料电阻值,看其与温度的关系是否符合规定。  (2)纯度校验法:即在0℃和100℃时,测量电阻值R0和R100,求出R100和R

热电阻元件有几种校验方法?

  热电阻元件一般有两种校验方法:  (1)分度校验法:即在不同温度点上材料电阻值,看其与温度的关系是否符合规定。  (2)纯度校验法:即在0℃和100℃时,测量电阻值R0和R100,求出R100和R

知识大全 php设计模式介绍之迭代器模式

  《PHP设计模式介绍》第八章迭代器模式  类中的面向对象编程封装应用逻辑类就是实例化的对象每个单独的对象都有一个特定的身份和状态单独的对象是一种组织代码的有用方法但通常你会处理一组对象或者集合  

知识大全 和田玉挂件,检验号A1806007733,校验码48454053值多少钱

和田玉挂件,检验号A1806007733,校验码48454053值多少钱  以下文字资料是由(本站网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶

知识大全 和田玉挂件,校验码3708 编号FX1505-LJT146244 这个值多少钱

和田玉挂件,校验码3708编号FX1505-LJT146244这个值多少钱  以下文字资料是由(本站网www.cha138.com)小编为大家搜集整理后发布的内容,让我们

知识大全 51单片机如何初始化成8-n-1(8数据位,无奇偶校验位,1停止位)波特率,是用串口的模式几

51单片机如何初始化成8-n-1(8数据位,无奇偶校验位,1停止位)波特率,是用串口的模式几?用串口的模式1,是10位异步通信方式。1起始位,8数据位,1停止位,没有奇偶校验位。这种模式就是:8-n-