Builder设计模式解析

242 阅读2分钟

Builder模式

  1. 目标:建一个复杂对象的构建和它的表示分离
使用场景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方法,

  • 良好的封装性,使用建造者模式可以使客户端不必知道产品内部的组成细节。
  • 建造者独立,易于拓展