没有内部 class 的构建器模式
Builder pattern without inner class
假设我有这个构建器模式。我到处搜索但找不到为什么我需要使用内部 class 如果外部 class 有 public consturctor.
public class User {
private final String firstName;
private final String surname;
private final int age;
public User(UserBuilder userBuilder) {
this.firstName = userBuilder.firstName;
this.surname = userBuilder.surname;
this.age = userBuilder.age;
}
public static class UserBuilder {
private final String firstName;
private final String surname;
private int age;
public UserBuilder(String firstName, String surname) {
this.firstName = firstName;
this.surname = surname;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public User build() {
User user = new User(this);
return user;
}
}
}
在这里我可以重写这段代码而不使用内部 class as :
public class User {
private String firstName;
private String surname;
private int age;
public User(String firstName, String surname) {
this.firstName = firstName;
this.surname= surname;
}
public User age(int age) {
this.age = age;
return this;
}
}
}
当我读到构建器模式时,他们说这种模式可以防止大的构造函数块。他们使用 inner with setters(具有流畅的模式)。我不明白为什么我们需要创建内部 class 如果我的构造函数是 public,我可以在不使用内部 class 的情况下做同样的事情。
这是更复杂变量的另一个示例:
class NutritionFacts {
private final int servingSize;
private final int servings;
private int calories;
private int fat;
private int sodium;
private int carbohydrate;
public NutritionFacts(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public NutritionFacts calories(int val)
{ calories = val; return this; }
public NutritionFacts fat(int val)
{ fat = val; return this; }
public NutritionFacts sodium(int val)
{ sodium = val; return this; }
public NutritionFacts carbohydrate(int val)
{ carbohydrate = val; return this; }
@Override
public String toString() {
return "NutritionFacts{" +
"servingSize=" + servingSize +
", servings=" + servings +
", calories=" + calories +
", fat=" + fat +
", sodium=" + sodium +
", carbohydrate=" + carbohydrate +
'}';
}
}
构建器模式不是为了提供流畅的样式创建(尽管这是一个很好的好处),它是为了在存在多个 可选 参数时提供合理的对象实例化。
没有意义
public User someOptionalParam(String someOptionalParam) {
this.someOptionalParam = someOptionalParam;
return this;
}
由于您获取的User
实例未完全构造,缺少非可选的名字、姓氏和年龄。
构建器模式在四人帮一书中得到普及(设计模式:可重用面向对象软件的元素)in a way that is not language specific。将构建器实现为内部 class 在 Java 语言的上下文中还有其他几个好处。
有效Java 给出一个构建器模式示例:
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
// Required parameters
private final int servingSize;
private final int servings;
// Optional parameters - initialized to default values
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val)
{ calories = val; return this; }
public Builder fat(int val)
{ fat = val; return this; }
public Builder sodium(int val)
{ sodium = val; return this; }
public Builder carbohydrate(int val)
{ carbohydrate = val; return this; }
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
Java 缺少使模式有用的某些语言功能。 Kotlin 具有命名参数和可选参数,允许将上面的示例编写为:
class NutritionFacts(
val servingSize : Int,
val servings: Int,
val calories: Int = 0;
val fat Int = 0,
val sodium Int = 0,
val carbohydrate Int = 0
)
val aFact = NutritionFacts(servingSize = 10, servings = 2, fat = 7)
编辑: 感谢您完成练习并以您的风格重新实施 NutritionFacts
。
你的实现的问题是它是可变的,它可变的唯一原因是你实现 "building" 部分的方式。这个特定的 class 本身没有任何东西需要可变性。
NutritionFacts aFact = new NutritionFacts(1,2).calories(7).sodium(3);
// ....
aFact.sodium(1).carbohydrate(9);
也许看起来我正在移动关于构建器模式通常应该实现的目标帖子,但我暗示
对此,当我说“作为内部 class 的构建器在 Java 语言的上下文中还有其他几个好处时。”
假设我有这个构建器模式。我到处搜索但找不到为什么我需要使用内部 class 如果外部 class 有 public consturctor.
public class User {
private final String firstName;
private final String surname;
private final int age;
public User(UserBuilder userBuilder) {
this.firstName = userBuilder.firstName;
this.surname = userBuilder.surname;
this.age = userBuilder.age;
}
public static class UserBuilder {
private final String firstName;
private final String surname;
private int age;
public UserBuilder(String firstName, String surname) {
this.firstName = firstName;
this.surname = surname;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public User build() {
User user = new User(this);
return user;
}
}
}
在这里我可以重写这段代码而不使用内部 class as :
public class User {
private String firstName;
private String surname;
private int age;
public User(String firstName, String surname) {
this.firstName = firstName;
this.surname= surname;
}
public User age(int age) {
this.age = age;
return this;
}
}
}
当我读到构建器模式时,他们说这种模式可以防止大的构造函数块。他们使用 inner with setters(具有流畅的模式)。我不明白为什么我们需要创建内部 class 如果我的构造函数是 public,我可以在不使用内部 class 的情况下做同样的事情。 这是更复杂变量的另一个示例:
class NutritionFacts {
private final int servingSize;
private final int servings;
private int calories;
private int fat;
private int sodium;
private int carbohydrate;
public NutritionFacts(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public NutritionFacts calories(int val)
{ calories = val; return this; }
public NutritionFacts fat(int val)
{ fat = val; return this; }
public NutritionFacts sodium(int val)
{ sodium = val; return this; }
public NutritionFacts carbohydrate(int val)
{ carbohydrate = val; return this; }
@Override
public String toString() {
return "NutritionFacts{" +
"servingSize=" + servingSize +
", servings=" + servings +
", calories=" + calories +
", fat=" + fat +
", sodium=" + sodium +
", carbohydrate=" + carbohydrate +
'}';
}
}
构建器模式不是为了提供流畅的样式创建(尽管这是一个很好的好处),它是为了在存在多个 可选 参数时提供合理的对象实例化。
没有意义
public User someOptionalParam(String someOptionalParam) {
this.someOptionalParam = someOptionalParam;
return this;
}
由于您获取的User
实例未完全构造,缺少非可选的名字、姓氏和年龄。
构建器模式在四人帮一书中得到普及(设计模式:可重用面向对象软件的元素)in a way that is not language specific。将构建器实现为内部 class 在 Java 语言的上下文中还有其他几个好处。
有效Java 给出一个构建器模式示例:
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
// Required parameters
private final int servingSize;
private final int servings;
// Optional parameters - initialized to default values
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val)
{ calories = val; return this; }
public Builder fat(int val)
{ fat = val; return this; }
public Builder sodium(int val)
{ sodium = val; return this; }
public Builder carbohydrate(int val)
{ carbohydrate = val; return this; }
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
Java 缺少使模式有用的某些语言功能。 Kotlin 具有命名参数和可选参数,允许将上面的示例编写为:
class NutritionFacts(
val servingSize : Int,
val servings: Int,
val calories: Int = 0;
val fat Int = 0,
val sodium Int = 0,
val carbohydrate Int = 0
)
val aFact = NutritionFacts(servingSize = 10, servings = 2, fat = 7)
编辑: 感谢您完成练习并以您的风格重新实施 NutritionFacts
。
你的实现的问题是它是可变的,它可变的唯一原因是你实现 "building" 部分的方式。这个特定的 class 本身没有任何东西需要可变性。
NutritionFacts aFact = new NutritionFacts(1,2).calories(7).sodium(3);
// ....
aFact.sodium(1).carbohydrate(9);
也许看起来我正在移动关于构建器模式通常应该实现的目标帖子,但我暗示 对此,当我说“作为内部 class 的构建器在 Java 语言的上下文中还有其他几个好处时。”