Builder模式
- 目标:建一个复杂对象的构建和它的表示分离
使用场景1:产品类非常复杂,这时候使用Builder模式就非常合适
计算机组装过程为构建主机,设置操作系统,设置显示器。
抽象的Product
public abstract class Computer {
protected String mBoard;
protected String mDisplay;
protected String mOs;
protected Computer() {}
public void setDisplay(String display) {
mDisplay = display;
}
public void setBoard(String board) {
mBoard = board;
}
...
}
具体的Product
public class MacBook extends Computer {
protected MacBook() {}
public void setOs() {
mOs = ".."
}
}
抽象的Builder
public abstract class Builder {
public abstract Builder buildBoard(String board);
public abstract Builder buildDisplay(String display);
public abstract Buidler buildOs();
public abstract Computer build();
}
具体的Builder
public class MacBookBuilder extends Builder {
private Computer mComputer = new MacBook();
public Builder buildBoard(String board) {
mComputer.setBoard(board);
return this;
}
public Builder buildDisplay(String display) {
mComputer.setDisplay(display);
return this;
}
public Builder buildOs() {
mComputer.setOs();
return this;
}
public Computer build() {
return mComputer;
}
}
如果想要链式创建一台macbook:
MacBook mac = new MacBookBuilder().buildDisplay("显示器").buildBoard("主板").buildOs().build();
使用场景2:当初始化一个对象特别复杂,参数特别多,且许多参数都有默认值时,使用Builder模式很合适
如果一个类表示包装食品外面显示的营养成分标签,这些标签中有几个域是必需的:每份的含量,每罐的含量以及每份的卡路里。还有超过20个可选域:总脂肪量,饱和脂肪量等等。对于这样的类,应该使用哪种构造器来编写呢。
建造者模式
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 {
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 sodium(int val) {
sodium = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}
public Builder carbohydrate() {
carbohydrate = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this)
}
}
private NutrtionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
链式调用实例
NutrionFacts coca = new NutritionFacts.Builder(240,8).calories(100).build();
总结:Builder模式,通常是作为配置类的构建器将配置的构建和表示分离开来,同时也是将配置从目标类中隔离出来,避免过多的setter方法,
- 良好的封装性,使用建造者模式可以使客户端不必知道产品内部的组成细节。
- 建造者独立,易于拓展