我们需要 Builder 模式中的 .build() 方法吗?

Do we need a .build() method in the Builder Pattern?

我对 "Effective Java" 中涵盖的 "Builder Pattern" 有疑问。我们是否需要 .build() 方法才能正确实现该模式?例如,假设我们有以下 class:

public class CoffeeDrink {

    private int numEspressoShots;
    private short milkType;
    private boolean withWhip;

    private CoffeeDrink() {
    }

    public static CoffeeDrink buildNewDrink() {
        return new CoffeeDrink();
    }

    public CoffeeDrink withEspresso(int n) {
        this.numEspressoShots = n;
        return this;
    }

    public CoffeeDrink withMilkType(shot t) {
        this.milkType = t;
        return this;
    }

    public CoffeeDrink withWhip() {
        this.withWhip = true;
        return this;
    }
}

然后我们如何使用它:

CoffeeDrink c = CoffeeDrink.buildNewDrink()
                         .withEspresso(2)
                         .withMilkType(2)
                         .withWhip();

如果我没有静态内部 Builder class,这仍然有效吗?我想其中一个优点是它在调用方法 .build() 之前不会创建新的 CoffeeDrink 对象,但我仍在创建 Builder 对象。只是寻求一些澄清。

不,这不是构建器模式。它是有效的 Java,它将编译并 运行。但是您的 buildNewDrink() 方法,无论它被称为 build()buildNewDrink() 还是其他名称,都只是一个创建 CoffeeDrink 的简单工厂方法。那些其他方法就像 setter 发生在 return 自己身上的方法。

static 嵌套生成器 class 是必需的。在推迟创建 class 实例时,它可以执行验证逻辑以确保不会创建无效对象。我不确定 CoffeeDrink 是否存在无效状态,但如果确实如此,使用您的代码,可以创建 CoffeeDrink 并将其置于无效状态创建之后,但在调用其他方法之前的状态。 Builder 模式通过在构建实例之前验证数据来消除这种可能性。它还消除了构造函数爆炸的需要,其中需要大量具有所有可能参数组合的构造函数,以涵盖所有可能的情况。

根据 GoF 参考,build() 不是必需的。原始引用不使用链接,并且在 Director.construct() 方法的末尾有一个 getResult() 步骤。 Director class 负责封装构建过程,因此 Client 无需担心构建是否正确。这是 Director.

的责任

这是来自 GoF 参考资料中关于 Builder 的序列图: