定义与结构
GOF 给建造模式的定义为:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。这句话说得很抽象,不好理解,其实它的意思可以理解为:将构造复杂对象的过程和组成对象的部件解耦。就像攒电脑一样,不管什么品牌的配件,只要兼容就可以装上;同样,一样的配件,可以有好多组装的方式。这是对降低耦合、提高可复用性精神的一种贯彻。当要生成的产品有复杂的内部结构——比如由多个对象组成;而系统中对此产品的需求将来可能要改变产品对象的内部结构的构成,比如说产品的一些属性现在由一个小对象组成,而更改后的型号可能需要N 个小对象组成;而且不能将产品的内部构造完全暴露给客户程序,一是为了可用性,二是为了安全等因素。满足上面的设计环境就可以考虑使用建造模式来搭建框架了。
简单的说:建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
来看看建造模式的组成吧。
1) 抽象建造者角色(Builder):这个角色用来规范产品对象的各个组成成分的建造。一般而言,此角色独立于应用程序的业务逻辑。
2) 具体建造者角色(ConcreteBuilder):担任这个角色的是于应用程序紧密相关的类,它们在指导者的调用下创建产品实例。这个角色在实现抽象建造者角色提供的方法的前提下,达到完成产品组装,提供成品的功能。
3) 指导者角色(Director):调用具体建造者角色以创建产品对象。指导者并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者对象。
4) 产品角色(Product):建造中的复杂对象。它要包含那些定义组件的类,包括将这些组件装配成产品的接口。
来看下这些角色组成的类图:
首先客户程序创建一个指导者对象,一个建造者角色,并将建造者角色传入指导者对象进行配置。然后,指导者按照步骤调用建造者的方法创建产品。最后客户程序从建造者或者指导者那里得到产品。
从建造模式的工作流程来看,建造模式将产品的组装“外部化”到了建造者角色中来。这是和任何正规的工厂模式不一样的——产品的创建是在产品类中完成的。
建造者模式的实现
//产品角色--Product
public class Starbucks {
private String size;
private String drink;
public void setSize(String size) {
this.size = size;
}
public void setDrink(String drink) {
this.drink = drink;
}
}
//抽象建造者角色--Builder
public 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();
}
//具体建造者角色--ConcreteBuilderA
public 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");
}
}
//具体建造者角色--ConcreteBuilderB
public 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");
}
}
//指导者角色--Director
public 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();
}
}
//顾客
public class Customer {
public static void main(String[] args) {
Waiter waiter = new Waiter();
StarbucksBuilder coffeeBuilder = new CoffeeBuilder();
//也可以用泡茶builder沏茶
//StarbucksBuilder teaBuilder = new TeaBuilder();
waiter.setStarbucksBuilder(coffeeBuilder);
waiter.constructStarbucks();
//取到饮料
Starbucks drink = waiter.getstarbucksDrink();
}
}
输出结果:
a drink is created
build coffee
build medium size
从这点看出,建造者模式将很多功能集成到一个类里,这个类可以创造出比较复杂的东西。所以与工程模式的区别就是:工厂模式关注的是创建单个产品,而建造者模式则关注创建符合对象,多个部分。因此,是选择工厂模式还是建造者模式,依实际情况而定。