java代码重构思考
场景:
下面代码是当添加评论时,后端接收到数据后,处理数据并添加的过程
public Review getReview(ReviewParamsModel reviewParamsModel) {
Review review = new Review();
if (reviewParamsModel != null) {
review.setId(reviewParamsModel.getId());
review.setAimId(reviewParamsModel.getAimId());
review.setContent(reviewParamsModel.getContent());
review.setRemark(reviewParamsModel.getRemark());
review.setCreaterId(reviewParamsModel.getUserId());
review.setIdentityType(reviewParamsModel.getIdentityType());
review.setDeleted(Constant.DELETE_FALSE);
}
return review;
}
上边的代码,从逻辑上讲,是没有问题的,只是这种写法让我很厌烦,例子中字段不多,但如果有20个字段,我们要如何做呢? 一个一个进行set数据吗?当然,如果你这么做了,肯定不会有什么问题,但是,这肯定不是一个最优的做法。
有没有办法呢?我们现行的可以使用BeanUtils.copyProperties对代码进行重构和优化:
public Review convertToReview(ReviewParamsModel reviewParamsModel) {
Review review = new Review();
if (reviewParamsModel != null) {
BeanUtils.copyProperties(reviewParamsModel,review);
review.setCreaterId(reviewParamsModel.getUserId());
review.setDeleted(Constant.DELETE_FALSE);
}
return review;
}
1、优化了方法名字叫转化成评论更符合;2、使用工具BeanUtils.copyProperties,我们只需要把model对象和要转化的对象两个的属性值设置为一样的名称,并且保证一样的类型就可以了。这种方式让代码更加清晰、易懂!
这里有个疑问BeanUtils.copyProperties和JSONObject.parseObject哪个好一些?
在实际工作中,完成了几个对象转化时,我们会发现,这样的操作有很多很多,那么应该定义好一个接口,让所有这样的操作都有规则的进行。
如何操作呢查阅资料发现大致有两类情况可供我们选择
1、阅读springframework源码,发现org.springframework.core.convert.converter.Converter这样的定义:
public interface Converter<S, T> {
/**
* Convert the source object of type {@code S} to target type {@code T}.
* @param source the source object to convert, which must be an instance of {@code S} (never {@code null})
* @return the converted object, which must be an instance of {@code T} (potentially {@code null})
* @throws IllegalArgumentException if the source cannot be converted to the desired target type
*/
@Nullable
T convert(S source);
}
意思就是springframework中的Converter只是把原对象(source)转化为目标对象(target)
2、阅读了GUAVA的源码,发现了com.google.common.base.Convert这样的定义:
public abstract class Converter<A, B> implements Function<A, B> {
protected abstract B doForward(A a);
protected abstract A doBackward(B b);
//其他略
}
从源码可以了解到,GUAVA中的Converter可以完成正向转化和逆向转化,
这里我们尝试使用第二种方式,修改我们model中的代码:
public class ReviewParamsModel {
//省略
public Review converterToReview() {
ReviewParamsModelConverter reviewParamsModelConverter = new ReviewParamsModelConverter();
return reviewParamsModelConverter.convert(this);
}
public ReviewParamsModel convertFor(Review review){
ReviewParamsModelConverter reviewParamsModelConverter = new ReviewParamsModelConverter();
ReviewParamsModel convert = reviewParamsModelConverter.reverse().convert(review);
return convert;
}
private static class ReviewParamsModelConverter extends Converter<ReviewParamsModel, Review> {
@Override
protected Review doForward(ReviewParamsModel reviewParamsModel) {
Assert.notNull(reviewParamsModel, "reviewParamsModel不能为空");
Review review = new Review();
BeanUtils.copyProperties(reviewParamsModel, review);
review.setCreaterId(reviewParamsModel.getUserId());
review.setDeleted(Constant.DELETE_FALSE);
return review;
}
@Override
protected ReviewParamsModel doBackward(Review review) {
Assert.notNull(review, "review不能为空");
ReviewParamsModel reviewParamsModel = new ReviewParamsModel();
BeanUtils.copyProperties(review, reviewParamsModel);
return reviewParamsModel;
}
}
调用层:
public Review convertToReview(ReviewParamsModel reviewParamsModel) {
//正向转化
Review review = reviewParamsModel.converterToReview();
//逆向转化
//ReviewParamsModel reviewParamsModel1 = reviewParamsModel.convertFor(review);
return review;
}
对于有些业务是无法逆向转换的那么我们只需要告诉程序:逆向是无法调用的: