关于此主题的文章很多(绝大多数),但我只是想贡献我的两分钱,写一篇简短的文章,介绍如何使用Java中的Fluent Object Creation模式或对象构建器实例化Value Objects。
值对象是由其状态(值)而不是其在内存中的地址定义的抽象。 价值对象的示例是诸如金钱,数字,坐标等之类的东西。它们不是用来描述业务对象,而是用于描述具体不可分割的实体。 此外,它们是将其添加到收藏和地图的绝佳选择。
在Java中, Value Objects应该声明为final,并且不提供setter方法,基本上使它在创建后保持不变,这是非常重要的
需求。 最终声明它们会使它们无法充当父对象。 这是通过设计完成的,因为价值对象应该对小的具体实体进行建模。 原因是我们应该能够创建和比较这些对象的多个副本,这总是由状态而不是通过引用来完成。 另外,您应该声明适当的equals()和hashCode()方法以符合适当的值对象的条件。 在C ++中,适用相同的原理。 在C ++中,您应该使用Copy构造函数并重载赋值和比较运算符。 流利的对象创建模式使价值对象实例化优雅而干净。 很快就会看到,使用流畅的对象创建可以带来很多好处。
从API用户的角度来看,应用此模式的最终结果将如下所示:
Money fiveEuros = new Money.Builder().currency(Currency.EURO).value(5.0L).countryOfOrigin("Spain").type("Coin").reverse("Map of Europe").obverse("Map of Spain").addColor("Bronze").addColor("Silver").year("1880")
.build();
我认为您会同意,这种模式与之相反,流程更加顺畅:
Money fiveEuros = new Money();
fiveEuros.setCurrency(Currency.EURO);
fiveEuros.setValue(5.0L);
fiveEuros.countryOfOrigin("Spain");
fiveEuros.type("Coin");
fiveEuros.reverse("Map of Europe");
fiveEuros.obverse("Map of Spain");List<String> colors = new ArrayList<String>();
for(String color: new String[] {"Bronze", "Silver"}) {colors.add(color);
}fiveEuros.setColors(colors);
fiveEuros.setYear("1880");
这似乎坏了,并且有很多打字和重复。 在我看来,这是一个构建非常大的价值对象的示例,其中大多数往往很小。 在讨论以这种方式创建对象的好处之前,让我们看一下这种模式的结构:
public final class Money {private Long value;private String countryOfOrigin; private Currency currency;private String type; private String reverse;private String obverse; private List<String> colors;private Date year; private Money() { }// -- getters, hashCode, equals -- //// Static inner Builder classpublic static class Builder {private Money _temp = new Money();
public Builder value(Long val) {
_temp.value = val;
return this;
}
public Builder countryOfOrigin(String countryOfOrigin) {
_temp.contryOfOrigin = countryOfOrigin;return this;
}
public Builder currency(Currency c) {
_temp.currency = c;
return this;
}
public Builder type(String t) {
_temp.type = t;
return this;
}
public Builder reverse(String r) {
_temp.reverse = r;
return this;
}public Builder obverse(String o) {
_temp.obverse = o;
return this;
}public Builder addColor(String c) {
if(_temp.colors == null) {_temp.colors = new ArrayList<String>(); }_temp.colors.add(c);
return this;
}public Builder year(String y) {if(y == null || y.isEmpty()) {_temp.year = new Date();}else {_temp.year = DateFormat.parse(y);}
return this;
}
public Money build() {// Validate objectif(Strings.isNullOrEmpty(_temp.name) || _temp.currency == null) {throw new IllegalArgumentException("Coin currency and value required");}
return _temp;
}}
}
这也是一个问题,但是我更喜欢静态内部类方法。 我喜欢将构建者称为“规范性”
Money.Builder。 还需要将其设为静态 ,因为构建器实例需要独立于封闭类生活。 我喜欢这种模式,因为它具有以下优点:
- 更大的对象封装:通过将Money构造函数设为私有(这只是样式),我可以轻松地使用构建器强制执行对象构造。 这完全隐藏了创建该对象的所有复杂性:列表创建,日期解析等。从用户的角度来看,最终得到的是一个易于实例化的对象。 我的插图很简单,但是可以想象更复杂的对象图。
- 代码可读性:使用此模式创建对象,使单元测试和代码非常易于阅读和遵循。
- 长期减少键入:即使您必须为每个添加的属性添加额外的构建器方法,但长期保存的键入量还是值得的。
结论
使用流畅的创建模式需要更多的工作,但是最终获得回报的好处。 它使实例化对象非常优雅和干净。 您不必将其与Value Objects一起使用,使用Fluent Object Creation的大多数好处是当您需要构建相当复杂的对象图时,但是我想证明它也可以适用 小价值的对象。
参考:我们的JCG合作伙伴 Luis Atencio在Reflective Thought博客上的Fluent Object Creation 。
翻译自: https://www.javacodegeeks.com/2013/01/fluent-object-creation.html