为了简单起见,我将使用批注lombok'a:
@Value
@Builder
经过一番谷歌搜索后,我们得到了该生成器-将复杂对象的构造与其表示分离开来,以便通过相同的设计过程获得不同的视图。它仅适用于复杂对象吗?
让我们看一个简单的例子:
@Value
public class Info {
@Nullable String uuid;
@Nullable String email;
@Nullable String phone;
}
很简单的一堂课。实际上,我们得到了一个通过构造函数初始化的不可变对象。
但是,正如我们所看到的,所有字段都是可为空的,并且创建这样的对象看起来不会很好:
final Info info1 = new Info(null, "email@email.com", "79998888888");
final Info info2 = new Info("3d107928-d225-11ea-87d0-0242ac130003", null, null);
final Info info3 = new Info("3d107928-d225-11ea-87d0-0242ac130003 ", "email@email.com", null);
...
当然有选择:
- 具有几个不同类型字段的对象可以通过几个构造函数来传递。但这并不能解决上述类的问题。
- 使用设置器是主观的,它会使代码混乱。
那建设者呢?
@Value
@Builder
public class Info {
@Nullable String uuid;
@Nullable String email;
@Nullable String phone;
}
我们得到了一个非常优雅的简单对象构造:
final Info info1 = Info.builder()
.uuid("3d107928-d225-11ea-87d0-0242ac130003")
.phone("79998888888")
.build();
final Info2 info2 = Info.builder()
.email("email@email.com")
.phone("79998888888")
.build();
...
}
但是,要在项目中使用杰克逊,有必要补充我们的课程,以使其成功反序列化:
@Value
@Builder(builderClassName = "InfoBuilder")
@JsonDeserialize(builder = Info.InfoBuilder.class)
public class Info {
@Nullable String uuid;
@Nullable String email;
@Nullable String phone;
@JsonPOJOBuilder(withPrefix = "")
public static class InfoBuilder {
}
}
对于这两种方法,我们各有利弊:
builder:
+
1.代码变得更加简洁。
3.构造函数参数中的null不明显。
2.减少混淆相同类型参数的机会。
-1
.我们创建了一个额外的对象,整个GC都可以安全地删除该对象,但是您不要忘记它。
2.如有必要,请使用杰克逊-上课。
构造函数:
+
1.最小程度地堆满我们的课程,没有水。
2.没有不必要的对象创建。
-1
.通常,null会到达此类对象的构造函数。
2.当有人更改密码时,可能会出错。
结果
根据我的经验,我倾向于使用构建器。成本不高,但是输出是易于阅读的代码。
当然,编写测试以避免使用构造函数的第二个缺点。
PS:这是我的第一篇文章,对于建设性的批评和意见,我将不胜感激。