有句话叫做“计算机科学领域任何问题,都可以间接的通过添加一个中间层来解决”,但是唯一解决不了的问题,是层次本身过多的问题。每一层内都会维护自己在乎的数据对象模型。层与层之间数据的传递,就不可避免地遇到对象类型转换的问题。
这个话题也和最近的项目有关。我们在重构一个老旧的系统,所做的第一件事情,就是要把数据访问层从原有系统中剥离出来,我们精心设计了这一层的模型和结构,但是要让原有系统平缓地从原有数据访问方式上移植到新的数据访问层上,就涉及到上层(Service)的原有数据对象和数据访问层(DAS)之间的数据传递,而二者模型并不相同,而且原有Service的模型并不纯粹,既不是充血模型,model层也掺杂了很多逻辑,因此也不是纯粹的贫血模型,因此这两层之间对象转换的工作就显得尤为重要。
且看这样的对象转换:
public UserNew transform(UserOld old){
UserNew userNew = new UserNew();
userNew.setName(old.getName());
userNew.setAge(old.getAge());
userNew.setSex(old.getSex());
userNew.setDesc(old.getDesc());
... ...
}
public UserOld transform(UserNew newUser){
... ...
}
|
但是在使用过程中,发现存在着这样一些问题:
- 一个UserNew/UserOld对象有40个属性,这样的一次transform就要写40+行这样毫无营养的get/set代码,而再提供一个反向转换的方法这样的代码需要×2;整个系统存在二三十种model,这样啰嗦的转换令人恶心;再者,我们发现,层次可能很多——比如我们在使用一些序列化框架时,需要借由类似的方法将当前对象转换成框架需要的POJO对象,因此一个User就让我们做了很多次这样丑陋的转换。
- 转换并不是那么顺利的,经常遇到类型不同的情况,需要经过类型转换或者简单的逻辑处理。比如对于空值的特殊处理,对于0值的特殊处理等。
-
转换甚至都不一定是一对一的,特殊情形的处理被迫使用到的逻辑,让整个转换层和业务模块中的很多发生耦合……这不是我希望看到的。
如何思考和解决这样的问题?其实这个问题有很多种表现形式,比如PO-VO对象的互转换等等。这里的争论很多,我整理如下:
1、如果能够尽量保证模型的字段名和和类型一致,可以利用Spring的copyProperties方法来完成POJO对象的拷贝:
BeanUtils.copyProperties(srcObj, desObj);
|
不过这个方法也有一些缺陷,一个是反射导致的性能损失,一次反射并不明显,对象拷贝可以说是非常频繁的;还有一个是对于一些类型不同的情况,我们需要自定义一些转换逻辑来处理这样的特殊情形。
2、借由一个中间层来承载数据,这样的中间层往往是可序列化的,比如JSON格式,每一种String、int等基础的类型都有转换成JSON的统一处理办法,所有数据的转换都通过通用方法转成JSON格式,然后再根据目标对象对各字段格式的要求,把JSON表示的对象复原。这种办法需要的框架性代码比较多,而且通过序列化对象作为中间介质,不免存在性能损耗的问题,但是对于存在大量数据转换的情况,也不失为一种好办法:
3、如果是使用Ruby之类的动态语言,或者变量定义本身就是弱类型的,那么就会省去很多这样转换的工作,当然,由于编译期间对于对象属性的不确定性,也可能引入更多不可预期的运行时异常,或者是一些丢失精度、显示错乱等等这方面的问题。
4、还有一个走极端的方式,对象变成Map<String, String>来存储,这样就免去了对象转换的成本,而且扩展性极强。但是缺点也是极其明显的,这就根本不是面向对象了,这是“面向无差异数据容器”编程……而且缺少约束,对于嵌套场景可读性极差。
5、在某些情况下还有一个变通的方式,我们不减少任何这样对象转换的重复代码,但是,我们可以通过注解、工具等等让这些可预期的代码自动生成,这同样减少了程序员的工作量。
最后,我要说的是,保持模型对象的纯粹和单一性,是减小工程重量的一个原则,让不同层次的逻辑使用同一组对象,虽然可能带来一些契合性问题、兼容性问题,但是带来的好处就是大大减小冗余对象类型的数量,减少这种没有营养的转换。这里又是trade off了。
除了这些,你还有什么体会和好办法?
文章系本人原创,转载请注明作者和出处(http://www.raychase.net)
注:本博客已经迁移到个人站点 http://www.raychase.net/ ,欢迎大家访问收藏,本ITEye博客在数日后将不再更新。
分享到:
相关推荐
Android应用源码之AndroidXstream(解决xml和对象转换问题)_应用
安卓Android源码——AndroidXstream(解决xml和对象转换问题).zip
安卓Android源码——AndroidXstream(解决xml和对象转换问题).rar
Android应用源码之AndroidXstream(解决xml和对象转换问题).zip项目安卓应用源码下载Android应用源码之AndroidXstream(解决xml和对象转换问题).zip项目安卓应用源码下载 1.适合学生毕业设计研究参考 2.适合个人学习...
C#对象转换类C#对象转换类C#对象转换类C#对象转换类C#对象转换类
本人自测非常好用,一般对象可以转化键值对的格式,但是最近项目需要自己手动拼接对象作为get请求的参数,百度了一堆还不如自己写一个,欢迎各位使用,有什么问题提出来哦,一起成长!!!
android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台
免责声明:资料部分来源于合法的互联网渠道收集和整理,部分自己学习积累... 本人尊重原创作者或出版方,资料版权归原作者或出版方所有,本人不对所涉及的版权问题或内容负法律责任。如有侵权,请举报或通知本人删除。
jQuery代码中采用了Array.prototype.slice把这种对象转换为数组,但我试了好几遍,就是不行: 代码如下: var obj = {}; obj[0] = 1; obj[1] = 2; alert(Array.prototype.slice.call(obj)); 上面这段代码在IE...
源码参考,欢迎下载
json格式与java类对象相互转换。json格式转换成java类对象,List,Map。类对象转换成json。
将数组转换成JSON对象,代码非常详细,可以下载看看
Android应用源码开发Demo,主要用于毕业设计学习。
c++对象转换 c++入门知识点,希望对大家有用
JSON转换为JAVA对象及日期格式转换处理 -
定义protobuf文件(包含enum,message,required,optional,repeated, 结构体定义中引用另一个结构体), 生成java文件,能够构建java对象,并转化为字节byte或者流,能够将流或字节转化为对象
C#对象和Xml对象的相互转化 C#对象和Xml对象的相互转化
NULL 博文链接:https://hw1287789687.iteye.com/blog/2188621
这是本人写的一个基于JSON的完整项目,实现了Java对象、数组、集合转换为Json(Json转化为Java对象、数组、集合)。这是一个完整的项目,下载解压后直接导入MyEclipse/Eclipse中,运行com.demo.JSONDemo类即可看到效果...
json-java对象转换包,实现客户端与JAVA服务器数据的轻松对接