一、介绍
建造模式(Builder)主要是为了将一个复杂的对象的构建和它的实际表示分离,使得同样的构建过程可以创建不同的表示。
建造模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们,用户不知道内部的具体构建细节,该模式非常类似与抽象工厂模式。
二、实例
在看建造模式的实例之前,请最好先理解抽象工厂模式(Abstract Factory) ,这里也依旧是上次那个炖汤的例子!先看看这个Builder模式的大致的UML图。
首先定义一个抽象的建造类SoupBuffetBuilder,和抽象工厂模式一样,在这个抽象类里定义了各种炖汤的制作方法。值得注意的是,这里和抽象工厂不同的是,其中额外定义了一个建造和获取目标集合对象的方法buildSoupBuffet()和getSoupBuffet(),所有的builder都是围绕这个soupBuffet展开,而不再直接返回一种炖汤。
abstract class SoupBuffetBuilder {
SoupBuffet soupBuffet;
public SoupBuffet getSoupBuffet() {
return soupBuffet;
}
public void buildSoupBuffet() {
soupBuffet = new SoupBuffet();
}
public abstract void setSoupBuffetName();
public void buildChickenSoup() {
soupBuffet.chickenSoup = new ChickenSoup();
}
public void buildClamChowder() {
soupBuffet.clamChowder = new ClamChowder();
}
public void buildFishChowder() {
soupBuffet.fishChowder = new FishChowder();
}
public void buildMinnestrone() {
soupBuffet.minnestrone = new Minnestrone();
}
public void buildPastaFazul() {
soupBuffet.pastaFazul = new PastaFazul();
}
public void buildTofuSoup() {
soupBuffet.tofuSoup = new TofuSoup();
}
public void buildVegetableSoup() {
soupBuffet.vegetableSoup = new VegetableSoup();
}
}
同样,接下来我们实例化这个builder抽象类和其中相关的子对象,类似于抽象工厂模式中的实例化过程。[波士顿]炖汤加工中心的代码BostonSoupBuffetBuilder如下:
class BostonSoupBuffetBuilder extends SoupBuffetBuilder {
public void buildClamChowder() {
soupBuffet.clamChowder = new BostonClamChowder();
}
public void buildFishChowder() {
soupBuffet.fishChowder = new BostonFishChowder();
}
public void setSoupBuffetName() {
soupBuffet.soupBuffetName = "Boston Soup Buffet";
}
}
class BostonClamChowder extends ClamChowder {
public BostonClamChowder() {
soupName = "QuahogChowder";
soupIngredients.clear();
soupIngredients.add("1 Pound Fresh Quahogs");
soupIngredients.add("1 cup corn");
soupIngredients.add("1/2 cup heavy cream");
soupIngredients.add("1/4 cup butter");
soupIngredients.add("1/4 cup potato chips");
}
}
class BostonFishChowder extends FishChowder {
public BostonFishChowder() {
soupName = "ScrodFishChowder";
soupIngredients.clear();
soupIngredients.add("1 Pound Fresh Scrod");
soupIngredients.add("1 cup corn");
soupIngredients.add("1/2 cup heavy cream");
soupIngredients.add("1/4 cup butter");
soupIngredients.add("1/4 cup potato chips");
}
}
class HonoluluSoupBuffetBuilder extends SoupBuffetBuilder {
public void buildClamChowder() {
soupBuffet.clamChowder = new HonoluluClamChowder();
}
public void buildFishChowder() {
soupBuffet.fishChowder = new HonoluluFishChowder();
}
public void setSoupBuffetName() {
soupBuffet.soupBuffetName = "Honolulu Soup Buffet";
}
}
class HonoluluClamChowder extends ClamChowder {
public HonoluluClamChowder() {
soupName = "PacificClamChowder";
soupIngredients.clear();
soupIngredients.add("1 Pound Fresh Pacific Clams");
soupIngredients.add("1 cup pineapple chunks");
soupIngredients.add("1/2 cup coconut milk");
soupIngredients.add("1/4 cup SPAM");
soupIngredients.add("1/4 cup taro chips");
}
}
class HonoluluFishChowder extends FishChowder {
public HonoluluFishChowder() {
soupName = "OpakapakaFishChowder";
soupIngredients.clear();
soupIngredients.add("1 Pound Fresh Opakapaka Fish");
soupIngredients.add("1 cup pineapple chunks");
soupIngredients.add("1/2 cup coconut milk");
soupIngredients.add("1/4 cup SPAM");
soupIngredients.add("1/4 cup taro chips");
}
}
不管加工中心如何,我们应该最初定一个目标集合对象SoupBuffet,可以把它理解为是一个集装箱吧!里面盛装了各种各样的炖汤。当然你也可以在里面公布一些额外的方法,比如说对这些炖汤的筛选或者组合等。
class SoupBuffet {
String soupBuffetName;
ChickenSoup chickenSoup;
ClamChowder clamChowder;
FishChowder fishChowder;
Minnestrone minnestrone;
PastaFazul pastaFazul;
TofuSoup tofuSoup;
VegetableSoup vegetableSoup;
public String getSoupBuffetName() {
return soupBuffetName;
}
public void setSoupBuffetName(String soupBuffetNameIn) {
soupBuffetName = soupBuffetNameIn;
}
public void setChickenSoup(ChickenSoup chickenSoupIn) {
chickenSoup = chickenSoupIn;
}
public void setClamChowder(ClamChowder clamChowderIn) {
clamChowder = clamChowderIn;
}
public void setFishChowder(FishChowder fishChowderIn) {
fishChowder = fishChowderIn;
}
public void setMinnestrone(Minnestrone minnestroneIn) {
minnestrone = minnestroneIn;
}
public void setPastaFazul(PastaFazul pastaFazulIn) {
pastaFazul = pastaFazulIn;
}
public void setTofuSoup(TofuSoup tofuSoupIn) {
tofuSoup = tofuSoupIn;
}
public void setVegetableSoup(VegetableSoup vegetableSoupIn) {
vegetableSoup = vegetableSoupIn;
}
public String getTodaysSoups() {
StringBuffer stringOfSoups = new StringBuffer();
stringOfSoups.append(" Today's Soups! ");
stringOfSoups.append(" Chicken Soup: ");
stringOfSoups.append(this.chickenSoup.getSoupName());
stringOfSoups.append(" Clam Chowder: ");
stringOfSoups.append(this.clamChowder.getSoupName());
stringOfSoups.append(" Fish Chowder: ");
stringOfSoups.append(this.fishChowder.getSoupName());
stringOfSoups.append(" Minnestrone: ");
stringOfSoups.append(this.minnestrone.getSoupName());
stringOfSoups.append(" Pasta Fazul: ");
stringOfSoups.append(this.pastaFazul.getSoupName());
stringOfSoups.append(" Tofu Soup: ");
stringOfSoups.append(this.tofuSoup.getSoupName());
stringOfSoups.append(" Vegetable Soup: ");
stringOfSoups.append(this.vegetableSoup.getSoupName());
return stringOfSoups.toString();
}
}
在建造模式里面,还应该有一个指导者(Director)类,它可以接受一个抽象建造类参数,并进一步包装、生产相应的集成产品。
class soupBuffetDirector {
private SoupBuffetBuilder soupBuffetBuilder;
public soupBuffetDirector(SoupBuffetBuilder soupBuffetBuilder) {
this.soupBuffetBuilder = soupBuffetBuilder;
}
public SoupBuffet CreateSoupBuffet() {
soupBuffetBuilder.buildSoupBuffet();
soupBuffetBuilder.setSoupBuffetName();
soupBuffetBuilder.buildChickenSoup();
soupBuffetBuilder.buildClamChowder();
soupBuffetBuilder.buildFishChowder();
soupBuffetBuilder.buildMinnestrone();
soupBuffetBuilder.buildPastaFazul();
soupBuffetBuilder.buildTofuSoup();
soupBuffetBuilder.buildVegetableSoup();
return soupBuffetBuilder.getSoupBuffet();
}
}
三、分析
通过以上建造模式的实例,我们可以总结出以下这些参与者:
- Builder 一个抽象类,其中包含了对各个部件建造的抽象定义。
- ConcreteBuilder 具体建造实现类,可以有一个或多个,实现创建具体部件的过程。
- AbstractProduct 抽象部件类,可以有一个或多个,为一类部件对象声明一个接口。
- ConcreteProduct 具体部件类,定义一个被相应的具体Builder类创建的部件对象,它继承或实现了相应的抽象部件类。
- Director 指导类,实际使用Builder对象的中介类,也是使用该建造模式的一般入口。
- Client 客户端,通过Director来实现建造模式。
实现一个建造模式,需要以下几个关键步骤:
1、定义一个抽象建造类,其中定义获取目标产品的建造以及出口,如buildObject和getObject。
2、定义一个或多个抽象建造类的实现类,顺带的定义了该实现类对应的实际产品种类等。
3、定义一个指导类,用抽象建造类作为参数,来实际使用已有的实际建造类。
建造模式(Builder)有着与抽象工厂模式(Abstract Factory) 一样的优缺点,它一般是用来创建一个比较复杂的大对象,里面包含了多步部件拼装的过程,而最终输出的是一个完整的大对象。
如果说和抽象工厂(Abstract Factory) 的目标是输出许多同等的产品的话,那么建造模式(Builder)应该就是输出一个完整的大对象,里面涵盖了许多个同等的子部件。