1、定义
建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
2、形式
建造者模式通用类图如下所示:
类图中各类含义为:
Product
为产品类,通常是实现了模板方法模式的类。
Builder
为抽象建造者,由其子类去实现实际产品的组建。
ConcreteBuilder
为具体建造者,实现抽象类定义的所有方法,并返回一个组建好的对象。
Director
为导演类,负责安排已有模块的顺序,然后告诉Builder开始建造。
通用源码如下:
Product
public class Product {
public void doSomething(){
//业务处理
}
}
Builder
public abstract class Builder {
//设置产品的不同部分,以获得不同的产品
public abstract void setPart();
//组建一个产品
public abstract Product buildProduct();
}
ConcreteBuilder
public class ConcreteBuilder extends Builder {
private Product product = new Product();
public void setPart() {
/*
* 产品类内的逻辑处理
* */
}
public Product buildProduct() {
return product;
}
}
Director
public class Director {
private Builder builder = new ConcreteBuilder();
//构建不同的产品
public Product getAProduct(){
/*
*逻辑代码
* */
builder.setPart();
/*
* 设置不同的零件生成不同的产品
* */
return builder.buildProduct();
}
}
示例:
抽象产品类采用模板方法模式定义产品对象,抽象产品构造者抽象出构建逻辑,由各个子类具体实现,导演类定义不同顺序的零件装配方式以生产不同的产品,场景类负责调用导演类获得产品对象。
AbstractProduct
public abstract class AbstractProduct {
private ArrayList<String> sequence = new ArrayList<String>();
//零件一
protected abstract void partOne();
//零件二
protected abstract void partTwo();
//零件三
protected abstract void partThree();
//组装过程
final public void getStructure(){
for (int i = 0; i < sequence.size(); i++) {
String partName = sequence.get(i);
if(partName == "partOne"){
this.partOne();
}else if(partName == "partTwo"){
this.partTwo();
}else if(partName == "partThree"){
this.partThree();
}
}
}
final public void setPart(ArrayList sequence){
this.sequence = sequence;
}
}
ProductA
public class ProductA extends AbstractProduct{
protected void partOne() {
System.out.println("A's partOne");
}
protected void partTwo() {
System.out.println("A's partTwo");
}
protected void partThree() {
System.out.println("A's partThree");
}
}
ProductB
public class ProductB extends AbstractProduct{
protected void partOne() {
System.out.println("B's partOne");
}
protected void partTwo() {
System.out.println("B's partTwo");
}
protected void partThree() {
System.out.println("B's partThree");
}
}
AbstractProductBuilder
public abstract class AbstractProductBuilder {
public abstract void setSequence(ArrayList<String> sequence);
public abstract AbstractProduct getProduct();
}
ProductABuilder
public class ProductABuilder extends AbstractProductBuilder{
private ProductA productA = new ProductA();
public AbstractProduct getProduct() {
return this.productA;
}
public void setSequence(ArrayList<String> sequence) {
this.productA.setPart(sequence);
}
}
ProductBBuilder
public class ProductBBuilder extends AbstractProductBuilder{
private ProductB productB = new ProductB();
public AbstractProduct getProduct() {
return this.productB;
}
public void setSequence(ArrayList<String> sequence) {
this.productB.setPart(sequence);
}
}
Director
public class Director {
private ArrayList<String> sequence = new ArrayList();
private ProductABuilder productABuilder = new ProductABuilder();
private ProductBBuilder productBBuilder = new ProductBBuilder();
//获得型号为1的产品A
public ProductA getProductA1Model(){
this.sequence.clear();
this.sequence.add("partOne");
this.sequence.add("partTwo");
this.sequence.add("partThree");
this.productABuilder.setSequence(this.sequence);
return (ProductA)this.productABuilder.getProduct();
}
//获得型号为2的产品A
public ProductA getProductA2Model(){
this.sequence.clear();
this.sequence.add("partThree");
this.sequence.add("partOne");
this.sequence.add("partTwo");
this.productABuilder.setSequence(this.sequence);
return (ProductA)this.productABuilder.getProduct();
}
//获得型号为3的产品B
public ProductB getProductB3Model(){
this.sequence.clear();
this.sequence.add("partTwo");
this.sequence.add("partThree");
this.sequence.add("partOne");
this.productBBuilder.setSequence(this.sequence);
return (ProductB)this.productBBuilder.getProduct();
}
}
Client
public class Client {
public static void main(String[] args) {
Director director = new Director();
System.out.println("型号为1的A产品结构组成为:");
director.getProductA1Model().getStructure();
System.out.println("型号为2的A产品结构组成为:");
director.getProductA2Model().getStructure();
System.out.println("型号为3的B产品结构组成为:");
director.getProductB3Model().getStructure();
}
}
3、优缺点
优点
- 封装性:使用建造者模式可以使客户端不必知道产品内部组成的细节。
- 建造者独立,容易扩展:可以通过扩展具体的建造者类来生成不同的产品。
- 便于控制细节风险:由于具体的建造者是独立的,因此可以细化建造过程而不对其他模块产生任何影响。
缺点:无
4、使用场景
- 相同的方法,不同的执行顺序会产生不同的事件结果时
- 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时
- 产品类非常复杂,或者产品类中调用顺序的不同产生了不同的效能(类似1)
- 当对象创建过程中会使用到系统中一些其他对象,但这些对象在产品的创建过程中不易得到(不佳的设计),可以采用建造者模式作为补偿方法封装该对象的创建过程。
注:建造者模式关注的是零件类型和产品装配顺序,这是该模式与工厂模式之间最大的区别,在实际设计过程中要避免混淆。(一个不太严谨的理解就是工厂专注于创建不同类型的积木,而建造则专注于用已经创建的积木去组合出不同的东西)
5、小结
建造者模式主要关注于产品创建过程,过程的不同会产生不用的创建结果。通常来说,使用建造者模式可以与模板方式结合(示例),把产品的各个内部零件的实现作为公共模板实现,而把零件的装配过程抽象出来,让建造者去进行实现。