我正在构建一个具有发动机、变速箱、离合器等的汽车类。 我不想要一个接受 7 个参数的臃肿构造函数,所以我决定使用构建器模式。 所有零件都是必需的。 但是,我如何让 Car 类的用户使用所有部件的 setter ,因为它们都是强制性的? 抛出异常?
public class Car {
private Engine engine;
private Chassis chassis;
private GearBox gearBox;
private Coupe coupe;
private Exterior exterior;
private Interior interior;
private Clutch clutch;
public Car(Builder builder) {
engine = builder.engine;
chassis = builder.chassis;
gearBox = builder.gearBox;
coupe = builder.coupe;
exterior = builder.exterior;
interior = builder.interior;
clutch = builder.clutch;
}
public static class Builder {
private Engine engine;
private Chassis chassis;
private GearBox gearBox;
private Coupe coupe;
private Exterior exterior;
private Interior interior;
private Clutch clutch;
private Car build() {
return new Car(this);
}
public Builder setEngine(@NonNull Engine engine) {
this.engine = engine;
return this;
}
public Builder setChassis(@NonNull Chassis chassis) {
this.chassis = chassis;
return this;
}
public Builder setGearBox(@NonNull GearBox gearBox) {
this.gearBox = gearBox;
return this;
}
public Builder setCoupe(@NonNull Coupe coupe) {
this.coupe = coupe;
return this;
}
public Builder setExterior(@NonNull Exterior exterior) {
this.exterior = exterior;
return this;
}
public Builder setInterior(@NonNull Interior interior) {
this.interior = interior;
return this;
}
public Builder setClutch(@NonNull Clutch clutchs) {
this.clutch = clutchs;
return this;
}
}
}
我希望用户调用所有构建器 setter ,而不是它们的可选子集。我该怎么做?
有没有另一种方法来构造汽车而无需使用需要这么多参数的庞大构造函数?
编辑:我查看了 The builder pattern and a large number of mandatory parameters但是没有解决方案可以阻止巨大的构造函数。
最佳答案
构建器适用于有很多部件是可选的或者您有许多不同配置的东西。 build()
方法然后确保特定配置有效。 HTML 构建器很有意义,字符串构建器就没那么有意义了。
如果没有可选部分,您有以下选择:
摆脱构建器并使用需要所有部件的构造器。经典解决方案,可读性最低且难以扩展。
您可以在
build()
方法中为每个缺失的部分抛出异常。需要编写大量代码,有点违反模式。您可以向构建器添加带有多个参数的方法。这是上述两者的混合。您仍在使用构建器模式(这样您以后可以轻松添加更多配置),但您的 API 也更清楚地传达了哪些部分是必需的。
例如,您将来可能会得到一台已经包含变速箱或需要特定变速箱的发动机(即,当您使用该发动机时,您还需要选择变速箱)。要实现这一点,您需要创建第二个构建器方法,该方法仅请求发动机并自动确定变速箱。
使用带有 protected 方法的工厂来构建零件。工厂将确保所有零件都供应给汽车。如果你想替换一个部分,你可以覆盖 protected 方法。如果您有很多默认值并且只有 2-3 个有用的配置,这会很有效。
使用多个生成器。与其用单个螺丝组装所有东西,不如用更大的构件来打造你的汽车:动力、内饰、车身。使用构造函数从这三个参数创建您的汽车(三个参数很好)。现在您可以使用三个构建器来创建这三个。尝试在必需元素和可选元素之间找到平衡点。
链 build 者 explained by mlk below .这会强制用户填写所有部分(因为您只能在链的末尾调用
build()
)。这里的主要缺点是: 由于代码分布在许多类中,因此从用户的角度来看,要编写大量代码并且难以遵循。 jOOQ是这里的一个例子;该项目将 SQL 语法实现为构建器链。
记住构建器模式试图解决的问题:它们使添加更多部分变得容易,因为所有现有代码都不需要更改如果新部分是可选的。如果新部分是必需的,那么构建器模式就会成为一种负担:使用巨大的(不可读的)构造函数,您会在所有需要修复的地方遇到编译错误。在这种情况下,构建器将在运行时失败;你需要一个 IDE 来找到所有需要修复的地方。
关于java - 如何使所有 Builder 方法成为必需的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33673302/