一、大白话
- 静态工厂和构造有个共同的局限性:不能很好的拓展到大量的可选参数中。
- 一般采用 重叠构造器模式 和JavaBeans模式,但这两种模式都各有缺陷。
- 而建造者模式既能保证重叠构造器模式那样的安全性,也能拥有像JavaBeans模式那样的可读性。
- Buidler模式是采用一个静态类Builder,来对属性进行赋值,然后再通过调用builder方法将属性值传递给外部类(真实的类)创建对象。
二、三种模式的优缺点
1、重叠构造器模式
- 直接看代码,当你的构造器有2个参数的时候,会调用3个的,接着调用4个的…
- 依次类推到每个参数都有初始值,这就是重叠构造器模式
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 NutritionFacts(int servingSize, int servings) {
this(servingSize, servings, 0);
}
public NutritionFacts(int servingSize, int servings,
int calories) {
this(servingSize, servings, calories, 0);
}
public NutritionFacts(int servingSize, int servings,
int calories, int fat) {
this(servingSize, servings, calories, fat, 0);
}
public NutritionFacts(int servingSize, int servings,
int calories, int fat, int sodium) {
this(servingSize, servings, calories, fat, sodium, 0);
}
public NutritionFacts(int servingSize, int servings,
int calories, int fat, int sodium, int carbohydrate) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = sodium;
this.carbohydrate = carbohydrate;
}
public static void main(String[] args) {
NutritionFacts cocaCola =
new NutritionFacts(240, 8, 100, 0, 35, 27);
}
}
① 优点
- 安全性还可以,这里指的安全性是构造器的对象A,和后面代码的对象A一致。
② 缺点
- 从代码可以看出,非常的繁琐,这里仅仅是6个参数就需要这么多代码,可想而知在10个参数,20个参数的时候,就失去控制了。
- 在许多参数的时候,客户端代码会很难编写,并且难以阅读。
- 在传参的时候,如果一不小心将参数的顺序颠倒,会导致错误。
2、JavaBeans模式
- JavaBeans模式是我们的学习JavaSE是最常用的一种模式,也是最容易编写的一种模式,采用无参构造器和setter方法来设置每一个参数。
public class NutritionFacts {
private int servingSize = -1;
private int servings = -1;
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0;
public NutritionFacts() { }
public void setServingSize(int val) { servingSize = val; }
public void setServings(int val) { servings = val; }
public void setCalories(int val) { calories = val; }
public void setFat(int val) { fat = val; }
public void setSodium(int val) { sodium = val; }
public void setCarbohydrate(int val) { carbohydrate = val; }
public static void main(String[] args) {
NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);
}
}
① 优点
② 缺点
- 在构造过程中JavaBean可能出一不一致状态:这里的不一致状态笔者的理解是,在构造的过程中,需要设置设置设置属性,在每一次设置的时候,都是不一样的状态。并且在设置的过程中,如果有客户端要来访问,那么访问到的可能是缺少属性的对象。
- JavaBeans模式使得把类做成不可变的可能性不复存在:这里的意思是有了set方法,那么构造出来的对象,就能被修改,那么程序员需要付出额外的努力来保证线程安全。
3、建造者模式
- 建造者模式是使用一个内部类进行属性的初始化,再通过一个buile()方法进行对象的创建。
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;
@Override
public String toString() {
return "NutritionFacts{" + "servingSize=" + servingSize + ", servings=" + servings + ", calories=" + calories + ", fat=" + fat + ", sodium=" + sodium + ", carbohydrate=" + carbohydrate + '}';
}
public static void main(String[] args) {
NutritionFacts cocaCola = new NutritionFacts.Builder(240 , 8).calories(100).sodium(35).carbohydrate(27).build();
System.out.println(cocaCola);
}
public static class Builder {
private final int servingSize;
private final int servings;
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;
}
}
① 优点
- 参数在设置的时候拥有了名字,可读性强。
- 安全性高,生成的对象拥有不可变性。
② 缺点
三、总结
- 如果类在后期需要添加参数,那么一开始就需要使用构建者模式,如果使用构造器或静态工厂方法,那么后期会无法控制。
- 如果类的构造器或静态工厂方法需要多个参数,那么优先考虑Builder模式。
- 特别是大多数参数可选或类型相同时,使用Buider模式,易于阅读和安全性高。