Builder建造者模式将一个复杂对象的构建与它的表示分离,使得一样的构建过程能够建立不一样的表示。Builder模式是一步一步建立一个复杂的对象,它容许用户能够只经过指定复杂对象的类型和内容就能够构建它们,用户不须要了解所构建对象的内部具体构建细节,Builder建造设计模式的目的是为了将构造复杂对象的过程和它的部件解耦。 java
Builder建造者设计模式中有两个重要角色:Director指导者和Builder建造者。Director指导者至关于设计师或架构师,拥有整个产品各个部件之间关系的构建蓝图。Builder建造者是部件的具体建立者,Builder建造者根据Director指导者的指示建立产品的各个部件,最终由Director构建出完整产品。Builder建造者设计模式的UML图以下: 设计模式
《Effective 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 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; } }
若是想要建立实例对象的时候,就利用参数列表最短的构造方法: app
NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0, 35, 27);若是可选参数不少的时候就难以控制,客户端代码变得很难编写,且难以阅读,若是不当心参数顺序混淆了,在编译的时候很难发现问题,在运行时出错时难以调试。
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){ this.servingSize = val; } public void setServings(int val){ this.servings = val; } public void setCalories(int val){ this.calories = val; } public void setFat(int val){ this.fat = val; } public void setSodium(int val){ this.sodium = val; } public void setCarbohydrate(int val){ this.carbohydrate = val; } }使用setter方法能够弥补重载构造方法的缺陷,建立实例对象很容易,而且代码也容易阅读:
NutritionFacts cocaCola = new NutritionFacts(); cocaCola.setServingSize(240); cocaCola.setServings(8); cocaCola.setCalories(100); cocaCola.setFat(27);因为javaBean自身有着很严重的缺点,构造过程被分到了几个调用中,在构造过程当中java Bean可能处于不一致的状态,类没法仅仅经过检验构造方法参数的有效性来保证一致性,使用处于不一致状态的对象将会致使失败。另外javaBean阻止了把类作成不可变的可能,所以很难确保线程安全。
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 final int calories = 0; private final int fat = 0; private final int sodium = 0; private final int carbohydrate = 0; public Builder(int servingSize, int servings){ this.servingSize = servingSize; this.servings = servings; } public Builder calories(int val){ this.calories = val; return this; } public Builder fat(int val){ this.fat = val; return this; } public Builder sodium(int val){ this.sodium = val; return this; } public Builder carbohydrate(int val){ this.carbohydrate = val; return this; } public NutritionFacts build(){ return new NutritionFacts(this); } } private NutritionFacts(Builder builder){ this.servingSize = builder.servingSize; this.servings = builder.servings; this.calories = builder.calories; this.fat = builder.fat; this.sodium = builder.sodium; this.carbohydrate = builder.carbohydrate; } }使用建造者模式建立实例对象:
NutritionFacts cocaCola = new NutritionFacts().Build(240, 8).calories(100).sodium(35).carbohydrate(27).build();建造者模式能够有多个可变参数,能够利用建造器构建多个对象,参数能够在建立时动态调整。
Builder建造者模式和AbstraceFactory抽象工厂模式的区别: ui
Builder建造者模式和AbstraceFactory抽象工厂模式很是相似,不少人常常分不清楚,区别以下: this
(1).抽象工厂模式中,每一次工厂物件被呼叫时都会传回一个完整的产品物件,而使用端有可能会决定把这些产品组装成一个更大的和复杂的产品,也有可能不会。工厂物件是没有状态的,不知道上一次构建的是哪个产品,也没有将来的概念,不知道下一次构建的是哪个产品,更不知道本身构建的产品在更高层的产品结构蓝图中是什么位置。换言之,虽然抽象工厂模式与建造模式都是设计模式,可是抽象工厂模式处在更加具体的尺度上,而建造模式则处于更加宏观的尺度上。一个系统能够由一个建造模式和一个抽象工厂模式组成,使用端经过呼叫这个导演角色,间接地呼叫另外一个抽象工厂模式的工厂角色。工厂样式传回不一样产品族的零件,而建造者模式则把它们组装起来。 spa
JDK中建造者模式的应用: 线程
StringBuilder和StringBuffer的append()方法使用了建造者模式。 设计