注:本文为译文,原文出处java-design-patterns-in-stories
生成器模式的核心功能是引入了逐步构造事物的过程. 例如: 每个产品的生产都会遵循相同的过程, 即使每一步都是不同的.
在下面的例子中, 我们定义了一个饮料的生成器StarbucksBuilder, 此生成器用于生产Starbucks饮品. StarbucksBuilder在生产饮料过程中包含若干个步骤, 例如buildSize()和buildDrink(), 以及最终返回的饮料.
package designpatterns.builder;
// produce to be built
class Starbucks {
private String size;
private String drink;
public void setSize(String size) {
this.size = size;
}
public void setDrink(String drink) {
this.drink = drink;
}
}
//abstract builder
abstract class StarbucksBuilder {
protected Starbucks starbucks;
public Starbucks getStarbucks() {
return starbucks;
}
public void createStarbucks() {
starbucks = new Starbucks();
System.out.println("a drink is created");
}
public abstract void buildSize();
public abstract void buildDrink();
}
// Concrete Builder to build tea
class TeaBuilder extends StarbucksBuilder {
public void buildSize() {
starbucks.setSize("large");
System.out.println("build large size");
}
public void buildDrink() {
starbucks.setDrink("tea");
System.out.println("build tea");
}
}
// Concrete builder to build coffee
class CoffeeBuilder extends StarbucksBuilder {
public void buildSize() {
starbucks.setSize("medium");
System.out.println("build medium size");
}
public void buildDrink() {
starbucks.setDrink("coffee");
System.out.println("build coffee");
}
}
//director to encapsulate the builder
class Waiter {
private StarbucksBuilder starbucksBuilder;
public void setStarbucksBuilder(StarbucksBuilder builder) {
starbucksBuilder = builder;
}
public Starbucks getstarbucksDrink() {
return starbucksBuilder.getStarbucks();
}
public void constructStarbucks() {
starbucksBuilder.createStarbucks();
starbucksBuilder.buildDrink();
starbucksBuilder.buildSize();
}
}
//customer
public class Customer {
public static void main(String[] args) {
Waiter waiter = new Waiter();
StarbucksBuilder coffeeBuilder = new CoffeeBuilder();
//Alternatively you can use tea builder to build a tea
//StarbucksBuilder teaBuilder = new TeaBuilder();
waiter.setStarbucksBuilder(coffeeBuilder);
waiter.constructStarbucks();
//get the drink built
Starbucks drink = waiter.getstarbucksDrink();
}
}
生成器模式被广泛应用于多个类库. 然而, 对此有一个普遍的误区. 参考如下样例, StringBuilder是一个JSL中的类. 它是否应用了生成器模式?
StringBuilder strBuilder= new StringBuilder();
strBuilder.append("one");
strBuilder.append("two");
strBuilder.append("three");
String str= strBuilder.toString();
在JSL中, StringBuilder继承于AbstractStringBuilder.
append()方法是类似于Starbucks例子中的一个步骤. toString方法则是过程中的最好一个步骤. 然后, 区别是没有Waiter. Waiter类在生成器模式中饰演了导演的角色. 由于没有这样一个角色, 因此上例并非生成器模式.
当然, 这不是唯一的原因. 你可以比较两者的类图, 从而找出另一个原因.
生成器模式作用的场景是:通过很多步骤去创建对象. 工厂模式的场景则是: 简单的调用一个方法就可以创建出整个对象.