1.定义
生成器是一种对象创建型的模式。生成器将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。
2.适用性
- 当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式时
- 当构造过程必须允许被构造的对象又不同的表示时
3.结构
Builder: 为创建一个Product对象的各个部件指定抽象接口。(工厂方法是为整个对象)
ConcreteBuilder: 实现Builder的接口以构造和装配该产品的各个部件;定义并明确它所创建的表示;提供一个检索产品的接口。
Director: 构造一个使用Builder接口的对象。
Product: 表示被构造的复杂对象,ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
4.举例说明
如图所示,Order类为导向器(Director),用来产生一个Builder的对象。MealBuilder就是抽象Builder,它的两个子类是AmericanMealBuilder和ChineseMealBuilder是具体Builder用于一步一步地构造meal的各个部分。Meal类是Product。TestMeal是测试类。
下面上源码:
Order.java:
package com.andy.designpattern.builder;
public class Order {
private MealBuilder mealBuilder;
public void makeOrder(MealBuilder mb){
mealBuilder = mb;
}
public void createMeal(){
mealBuilder.createMeal();
mealBuilder.buildMainFood();
mealBuilder.buildDrink();
mealBuilder.buildDish();
mealBuilder.buildSauce();
}
public Meal getMeal(){
return mealBuilder.getMeal();
}
}
MealBuilder.java:
package com.andy.designpattern.builder;
public abstract class MealBuilder {
protected Meal meal; // let child class see it
public Meal getMeal(){
return this.meal;
}
public void createMeal(){
meal = new Meal();
}
public abstract void buildMainFood();
public abstract void buildDrink();
public abstract void buildDish();
public abstract void buildSauce();
}
AmericanMealBuilder.java:
package com.andy.designpattern.builder;
public class AmericanMealBuilder extends MealBuilder {
public void buildMainFood() {
// TODO Auto-generated method stub
this.meal.setMainFood("fries");
}
public void buildDrink() {
// TODO Auto-generated method stub
this.meal.setDrink("coke");
}
public void buildDish() {
// TODO Auto-generated method stub
this.meal.setDish("hamburger");
}
public void buildSauce() {
// TODO Auto-generated method stub
this.meal.setSause("ketchup");
}
}
ChineseMealBuilder.java:
package com.andy.designpattern.builder;
public class ChineseMealBuilder extends MealBuilder {
public void buildMainFood() {
// TODO Auto-generated method stub
this.meal.setMainFood("rice,noodles");
}
public void buildDrink() {
// TODO Auto-generated method stub
this.meal.setDrink("soup");
}
public void buildDish() {
// TODO Auto-generated method stub
this.meal.setDish("vegetables and meat");
}
public void buildSauce() {
// TODO Auto-generated method stub
this.meal.setSause("peanut sause");
}
}
Meal
package com.andy.designpattern.builder;
public class Meal {
private String mainFood;
private String drink;
private String dish;
private String sause;
public String getMainFood() {
return mainFood;
}
public void setMainFood(String mainFood) {
this.mainFood = mainFood;
}
public String getDrink() {
return drink;
}
public void setDrink(String drink) {
this.drink = drink;
}
public String getDish() {
return dish;
}
public void setDish(String dish) {
this.dish = dish;
}
public String getSause() {
return sause;
}
public void setSause(String sause) {
this.sause = sause;
}
public String toString(){
return "MainFood:"+mainFood+"\nDrink:"+drink+"\nDish:"+dish+"\nSause:"+sause+"\n";
}
}
TestMeal.java:
package com.andy.designpattern.builder;
public class TestMeal {
public static void main(String[] args) {
MealBuilder chineseBuilder = new ChineseMealBuilder();
MealBuilder americanBuilder = new AmericanMealBuilder();
Order order = new Order();
order.makeOrder(chineseBuilder);
order.createMeal();
Meal meal1 = order.getMeal();
order.makeOrder(americanBuilder);
order.createMeal();
Meal meal2 = order.getMeal();
System.out.println("Chinese :\n"+meal1.toString());
System.out.println("American :\n"+meal2.toString());
}
}
控制台输出为:
Chinese :
MainFood:rice,noodles
Drink:soup
Dish:vegetables and meat
Sause:peanut sause
American :
MainFood:fries
Drink:coke
Dish:hamburger
Sause:ketchup
从例子中我们可以看到,我们仅仅是给导向器(Order类)传入了不同类型的MealBuilder引用,就从生成器当中得到了不同的产品。生成器模式很好地隐藏了产品实现的细节,将构造和表示分开。生成器模式常常是在Director中将产品分成许多部分,然后再Builder的中一部分一部分的构建出产品,最后再从Builder中将产品取出。 当定义的类的构造函数需要很多参数,使用起来非常不方便且缺乏灵活性,这时候可以考虑时候Builder模式,可以分步地构造各个部分。
5.相关模式
抽象工厂模式与生成器模式相似,都可以用于创建复杂的对象。主要区别是生成器模式是一步步地构造对象,产品在最后一步才返回,而抽象工厂是生产一系列(常常是多个)产品,并且立即返回产品。
参考资料:
2.Tutorialspoint: Builder Pattern