在 Java 中的另一个构建器中使用构建器



在Java中的另一个构建器中使用构建器是否是一种好的做法,或者最好将方法添加到"更高"级别的构建器中以在幕后创建对象?

new Car.CarBuilder().engine(new Engine.EngineBuilder().name("Diesel").weight(5).build()).build();

在另一个构建中重用构建器逻辑很好,正如 Andy Turner 在其评论中所说:您不想复制代码。
但是以这种方式执行链接确实不可读:

Car car = new Car.CarBuilder().engine(new Engine.EngineBuilder().name("Diesel").weight(5).build()).build();

您可以以不同的方式格式化它,但它仍然不是直接可理解的:

Car car = 
new Car.CarBuilder().engine(new Engine.EngineBuilder().name("Diesel").weight(5).build())
.build();   

在局部变量中提取Engine实例看起来非常清晰:

Engine engine = new Engine.EngineBuilder().name("Diesel").weight(5).build();
Car car = new Car.CarBuilder().engine(engine).build();

这最终是一个主观问题。

也就是说,作为对比:Google代码库中的Java代码使用了很多构建器,特别是对于协议缓冲区等数据对象。如果内联表达式足够,则有一种通用的风格偏好倾向于避免局部变量,这会导致许多代码看起来像您的示例。

一个显着的区别是Google风格鼓励一种称为矩形规则的东西(不幸的是,我找不到链接,尽管这里提到了它(。(我想说是约翰·德特雷维尔(John DeTreville(提出了这个想法,但我不是100%确定。实质上,矩形规则表示您希望语句中的每个表达式都适合矩形字符块。在表达式的矩形中可以有子表达式(每个子表达式都在各自的矩形内(,但外部表达式的任何部分都不应位于内部表达式的矩形内。

(当我在那里时,共识是外部表达式的结束参数不算作入侵内部矩形,但外部控制语句的右括号可以。显然,你可以花一整天的时间讨论这样的风格问题。

这意味着像你展示的东西的首选编写方式看起来更像:

Car car =
Car.builder()
.engine(
Engine.builder()
.name("Diesel")
.weight(5)
.build()
)
.build();

或者,更常见的是(稍微弯曲矩形规则(:

Car car = Car.builder()
.engine(
Engine.builder()
.name("Diesel")
.weight(5)
.build())
.build();

我个人认为最后一个例子最容易阅读:它紧凑而不忙碌,并引起人们对陈述的重要部分的注意,而不会因不重要的细节而分散注意力。文本的总体布局与数据结构相匹配,这也有助于理解。

当然,这只是一种风格选择。但是,一个非常大且成功的代码库做出了这种选择这一事实表明,以这种方式编写代码并没有,如果您喜欢这样做,您应该随时继续。

我更喜欢这种方法:
- 首先
构建引擎 - 然后使用专用的engine(...)设置器制造汽车

Engine engine = new EngineBuilder().name("Diesel").weight(5).build();
Car car = new CarBuilder().engine(engine).build();

最新更新