10.3 定制DTO
域DTO解决了在客户端和服务器端之间传递大量数据的问题,但是客户端往往需要更细粒度的数据访问。
例如,一件商品可能有很多属性:名称、编码、重量、型号、大小、颜色、生产日期、生产厂家、批次、保质期等。而客户端只对其中一部分属性有要求,如果将包含所有属性的商品对象到客户端的话,将会即浪费时间又浪费网络带宽,并对系统的性能有不同程度的影响。
我们需要一种可定制的DTO,使它仅封装客户端需要的数据的任意组合,完全与服务器端的域模型相分离。定制DTO与域DTO的区别就是它不映射到任何服务器端的域模型。
从上述的商品例子,设想客户端只需要一些与产品质量有关的属性,在这种情况下,应该创造一个封装了这些特定属性的DTO并传送给客户端。这个DTO是商品属性的一个子集:
public class GoodsCustomDTO implements Serializable
{
private Date productDate;
private Date expireDate;
private String batchNumber;
public GoodsCustomDTO(Date
productDate, Date expireDate, String
batchNumber)
{
super();
this.productDate = productDate;
this.expireDate = expireDate;
this.batchNumber = batchNumber;
}
public String getBatchNumber()
{
return batchNumber;
}
public Date getExpireDate()
{
return expireDate;
}
public Date getProductDate()
{
return productDate;
}
}
一般来说,如果客户端需要n个属性,那么应该创造一个包含且仅包含这n个属性的DTO。使用这种方法,域模型的细节被隐藏在服务器中。这样开发人员把DTO仅当做普通的数据,而不是任何像PO那样的服务端的业务数据。当然采用定制DTO系统中会有越来越多的DTO,所以很多开发者情愿使用粗糙一些的DTO(即包含比需要的属性多的属性),而不是重新编写一个新的DTO,只要是返回的冗余数据不是太多,还是可以接受的。毕竟对于任何一种技术,都需要寻求一个兼顾方便和性能的折衷点。
定制DTO主要用于只读操作,也就是DTO只能用来显示,而不能接受改变。既然定制DTO对象仅仅是一个数据的集合,和任何服务端对象没有必然的关系,那么对定制DTO进行更新就是没有意义的了。
定制DTO的缺点如下:
l 需要创建大量的DTO。使用定制DTO会爆炸式地产生大量的对象。
l 客户端DTO的版本必须和服务器端的版本一致。由于客户端和服务器端都通过定制DTO通信,所以一旦服务器端的DTO增加了字段,那么客户端的代码也必须重新编译,否则会产生类版本不一致的问题。






