Lombok的@Builder注解与构造函数的区别。

11

有人能向我解释使用 lombok @Builder 创建对象相对于构造函数调用的优势吗?

MyObject o1 = MyObject.builder()
              .id(1)
              .name("name")
              .build();

MyObject o2 = new MyObject(1, "name")

这只是一个更好的可见性的问题吗?


4
不是“可见性”,而是“易读性”。理论上,使用构建器可以做更多的事情,因为您可以传递半初始化的构建器。 - luk2302
3
建造者模式有一个缺点:它不会“强制”您提供所有必需的参数。因此,例如,如果您重构一些代码并向构造函数添加必需的参数,则在生成器调用者上不会产生编译错误... 但是您将遇到运行时故障。 - Joel
1
小心传递半初始化的构建器。它们是可变的。使用Lombok的一个重要原因是不可变对象。 - slim
可能是何时使用构建器模式?的重复问题。 - VLAZ
2个回答

17

考虑:

Order order = new Order("Alan", "Smith", 2, 6, "Susan", "Smith");

这些参数的含义是什么?我们需要查看构造函数的规范。

现在使用一个生成器:

Order order = Order.builder()
    .originatorFirstName("Alan")
    .originatorLastName("Smith")
    .lineItemNumber(2)
    .quantity(6)
    .recipientFirstName("Susan")
    .recipientLastName("Smith")
    .build();

这种写法可能有点啰嗦,但阅读起来非常清晰,而且在IDE的帮助下编写也很容易。撰写builder本身可能会有些烦人,但是像Lombok这样的代码生成工具可以提供帮助。

有人认为,如果你的代码需要使用builder才能读懂,那就暴露了其他问题。你使用了太多基本类型;你把太多字段放在一个类中。例如,请考虑以下内容:

Order order = new Order(
     new Originator("Alan", "Smith"),
     new ItemSet(new Item(2), 6),
     new Recipient("Susan", "Smith"));

由于我们正在使用更多具有单一职责的类和较少的字段,因此该内容可以自我解释,而无需使用构建器。


谢谢您的回答。但我有一个疑虑:为什么我们不这样初始化对象呢 Order order = new Order { firstName = “A”, lastName = “B”, } - Nguyễn Văn Phong
@NguyễnVănPhong 一种编程语言肯定可以这样工作,但Java不是这样的。 - slim
哦,我很惊讶。让我检查一下,如果有问题,我会尽快回复你。+1 - Nguyễn Văn Phong

12

这不是 lombok 特有的功能,而是称为建造者模式

假设您有一个包含20个参数的类,其中10个是可选的。你可以创建许多构造函数来处理这个逻辑,或者创建一个包含所有这些参数的构造函数,并在某些地方传递 null。使用建造者模式难道不更简单吗?


一个类应该只有一个单一的职责。通常,这与具有20个参数不相符。如果某个东西有20个字段,您可能更想退后一步,检查您是否真的在谈论一件事,或者应该将其拆分成几个更小的事情。 - GhostCat
1
@Builder 并不是您答案中提到的“四人帮”构建模式。建造者模式由指挥者和具体建造者组成,与 @Builder 提供的内容不同。 - Marc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接