嵌套类的使用方法之传输对象的种子

Creative Commons License
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。

 

嵌套类可用作生成传输对象的种子。

嵌套类

如果在一个类A中定义了另一个静态的类B,我们称A类为顶层类,B类为嵌套类(nested classes)。
如果在一个类A中定义了另一个非静态的类B,我们称A类为顶层类,B类为内部类(inner classes)。
嵌套类的语法要点在于,顶层类对象不可以访问嵌套类对象的成员,但嵌套类对象可以访问顶层类对象的所有成员,包括私有成员。例如:

嵌套类的这种语法特点对我们有何作用呢?

传输对象

传输对象(TransferObject)是J2EE分层体系中非常重要的元素,主要负责各层之间数据的传送。从应用角度来看,传输对象本身应该符合值对象(value objects)的要求,即该对象所对应的类是不可变类(immutable classes),这样可以保证各层使用数据时不会因误操作而引发领域模型的变化。
最易于作为传输对象使用的类是String类。String类是不可变类,其内容也相对简单(一个字符数组)。如果需要传送的数据结构相对复杂,也可以将数据转换成JSON字符串进行传输,关于JSON字符串的使用方法不在这里描述。
如果String类不能满足复杂数据结构的要求,我们就只能自己实现一个不可变类以满足需求。一个不可变类的实现要点包括:

  1. 将类中所有成员变量声明为private;
  2. 只提供取值函数(getter),不允许存在设值函数(setter);
  3. 将类声明为final,不允许子类化;
  4. 从取值函数返回可变对象的引用之前,先克隆(clone)这些可变对象;
  5. 如果传递给构造函数的数据中包含可变对象的引用,先克隆这些可变对象;
  6. 在构造函数中设定该类的所有成员变量。

例如一个文档(Document)由文档名(name)、作者名(writerName)、发布日期(date)组成。我们可以为其实现一个不可变类:

实现不可变类的详细描述可以参考Practical Java的实践63:审慎地定义和实现不可变类。

在这里我们要详细讨论最后一条:在构造函数中设定该类的所有成员变量。上例中DocumentTransferObject的构造函数有三个参数,创建一个DocumentTransferObject的过程如下:

如果一个类的构造函数的参数超过三个,那么代码的可读性将大打折扣。减少构造函数的参数个数的方法有很多,但适用于不可变类的却很少,主要原因在于不可变类没有设值函数。我们如何在不提供设值函数的前提下简化值对象的创建过程呢?利用嵌套类是其中一种比较简单并且直观的方法(注释1)。

嵌套类在值对象中的作用

根据嵌套类的语法特点,我们可以通过以下几个要点简化值对象的创建过程:

  1. 将不可变类的所有构造函数私有化;
  2. 为不可变类提供一个称为种子(Seed)的嵌套类,种子类内部保存一个私有的顶层类对象;
  3. 种子类提供设值函数,直接将数据设置到顶层类对象的私有成员上;
  4. 如果传递给设值函数的数据中包含可变对象的引用,先克隆这些可变对象;
  5. 种子类提供一个取值函数返回顶层类对象。

通过上述要点实现的不可变类如下:

我们可以首先创建种子,通过种子的设值函数设置属性,最后通过种子取得我们所需的值对象。代码如下:

至此,我们看到了一个非常简单而且直观的创建值对象的过程,种子的创建及设置属性的过程与一般的JavaBeans类没有区别。只要我们不将值对象的原始种子(上例中的docSeed对象)提供给第三方调用者使用,值对象就是安全的。
当然,我们可以在这个原始的种子类基础上完善其代码,使种子类更加严谨。例如在代码中增加值对象完整性的判断,要求在调用get方法之前所有属性必须设置完成。

注释1

另一种减少不可变类构造函数的参数个数的方法——以领域模型为参数的静态函数valueOf
作为一种Java文化,就象equals函数一样,valueOf函数也被Java赋予了特殊的含义。与equals函数的强制性不同,valueOf函数没有强制性,但valueOf通常以下面的方式出现:

  • 总是声明为静态函数;
  • 返回值的类型总是所在类的类型;
  • 参数可以是任意类型。

函数valueOf的基本功能是将传入的数据转换成valueOf所在类的对象并返回。换言之这是一个标准的工厂方法。如:

在J2EE的数据传输对象(DTO)模式中,传输对象总是从某一个领域模型的数据转换而来。因此在传输对象类中提供一系列valueOf函数并以领域模型为参数,也不失为减少不可变类构造函数的参数个数的一种方法。领域模型如:

传输对象如:

调用方法如:

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值