Builder模式 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
步骤:
- 创建一个导向器director并配置一个构建器builder;
- director通知builder去构建对象;
- 客户通过builder获取对象。
类图:
B u i l d e r对象提供给导向器(Director)一个构造产品的抽象接口;
每个具体生成器C o n c r e t e B u i l d e r包含了创建和装配一个特定产品的所有代码;改变该产品的内部表示时所要做的只是定义一个新的生成器。
B u i l d e r模式与一下子就生成产品的创建型模式不同,它是在导向者的控制下一步一步构造产品的。仅当该产品完成时导向者才从生成器中取回它。
Builder模式有多种实现方式:
方式1:生成器构建不同的产品。
每份的套餐构成算法相同: 一个米饭+一份荤菜+一份素菜+一份汤
套餐A: 一份米饭+一份排骨+一份生菜+一份鸡汤
套餐B : 一份米饭+一份牛肉+一份白菜+一份排骨汤
不同的套餐有不同的表示。
/**product**/
public class Meal {
private String meat;
private String vegetable;
private String rice;
private String soap;
public Meal() {}
public void setMeat(String meat) {
this.meat = meat;
}
public void setVegetable(String vegetable) {
this.vegetable = vegetable;
}
public void setRice(String rice) {
this.rice = rice;
}
public void setSoap(String soap) {
this.soap = soap;
}
public String getMeat() {
return meat;
}
public String getVegetable() {
return vegetable;
}
public String getRice() {
return rice;
}
public String getSoap() {
return soap;
}
}
/** buidler **/
public interface MealBuilder{
public void addRice();
public void addMeat();
public void addVegetable();
public void addSoap();
public Meal getMeal();
}
/** concrete builder **/
/**套餐A 一份米饭+一份排骨+一份生菜+一份鸡汤**/
public class MealBuilderA implements MealBuilder {
private Meal meal = new Meal();
public void addRice() {
meal.setRice("normal");
}
public void addMeat() {
meal.setMeat("chopstick");
}
public void addVegetable() {
meal.setVegetable("lettuce");
}
public void addSoap() {
meal.setSoap("chicken soap");
}
public Meal getMeal() {
return meal;
}
}
/** concrete builder **/
/**套餐B 一份米饭+一份牛肉+一份白菜+一份排骨汤**/
public class MealBuilderB implements MealBuilder {
private Meal meal = new Meal();
public void addRice() {
meal.setRice("normal");
}
public void addMeat() {
meal.setMeat("beaf");
}
public void addVegetable() {
meal.setVegetable("cabbage");
}
public void addSoap() {
meal.setSoap("chopstick soap");
}
public Meal getMeal() {
return meal;
}
}
当客户点套餐A时,服务员(Director)根据构建器MealBuilderA构建A套餐,
当客户点套餐B时,服务员(Director)根据构建器MealBuilderB构建B套餐。
/** director **/
public class MealDirector {
private MealBuilder builder
public MealDirector(MealBuilder builder) {
this.builder = builder;
}
/** construct method of Direcrotor **/
public void buildMeal() {
builder.addRice();
builder.addMeat();
builder.addVegetable();
builder.addSoap();
}
}
客户代码
public class Client {
public static void main(String[] args) {
MealBuilder mealBuilderA = new MealBuilderA(); // 点 A 套餐
MealDirector directorA = new MealDirector (mealBuilderA);
director.buildMeal();
Meal mealA = mealBuilderA.getMeal(); //return A 套餐
MealBuilder mealBuilderB = new MealBuilderB(); // 点 B 套餐
MealDirector directorB= new MealDirector (mealBuilderB);
directorB.buildMeal();
Meal mealB = mealBuilderB.getMeal(); //return B 套餐
}
}
上面的Director可以变体为:
public class MealDirectorX {
/**
* construct method of Direcrot
**/
public static Meal buildMeal(MealBuilder mealBuilder) {
mealBuilder.addRice();
mealBuilder.addMeat();
mealBuilder.addVegetable();
mealBuilder.addSoap();
return mealBuilder.getMeal();
}
}
public class ClientX {
public static void main(String[] args) {
MealBuilder mealBuilderA = new MealBuilderA(); // 点 A 套餐
Meal mealA = MealDirectorX.buildMeal(mealBuilderA); //return A 套餐
MealBuilder mealBuilderB = new MealBuilderB(); // 点 B 套餐
Meal mealB = MealDirectorX.buildMeal(mealBuilderB); //return B 套餐
}
}
方式2:
当一个类的构造器的参数列表很长时,可以用公有静态内部类作为辅助类构建对象。
public class Product {
private String name;
private float price;
private Color color;
private ProductSize size;
private Person(Builder builder) {
this.name = builder.name;
this.price = builder.price
this.color= builder.color;
this.size= builder.size;
}
public static class Builder {
private String name;
private float price;
private Color color;
private ProductSize size;
public Builder(String name) {
this.name = name;
}
public Builder price(float price) {
this.price= price;
return this;
}
public Builder color(Color color) {
this.color= color;
return this;
}
public Builder size(ProdcutSize size) {
this.size= size;
return this;
}
public Product build() {
return new Product (this);
}
}
}
enum ProductSize {
SMALL, MEDIUM, LARGE, NOT_APPLICATION
}
方式3:
public class Product {
private String name;
private float price;
private Color color;
private ProductSize productSize;
private Product(String name) {
this.name = name;
}
public static Product withName(String name) {
return new Product(name);
}
public Product withColor(Color color) {
this.color = color;
return this;
}
public Product withSize(ProductSize productSize) {
this.productSize = productSize;
return this;
}
public Product withPrice(float price) {
this.price = price;
return this;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
public Color getColor() {
return color;
}
public ProductSize getProductSize() {
return productSize;
}
}
enum ProductSize {
SMALL, MEDIUM, LARGE, NOT_APPLICATION
}
客户代码:
public class ProductClient {
public static void main(String[] args) {
// method 1:
Product.Builder builder = new Product.Builder("A");
Product prodcut = builder.color(Color.red)
.size(ProductSize.SMALL).price(20.00f)
.build();
// method 2:
Product product2 = Product.withName("A")
.withColor(Color.red)
.withSize(ProductSize.SMALL)
.withPrice(20.00f);
}
}
返回 模式与重构