Builder-建造者模式

## 前言

当一个对象的构造十分复杂时,我们需要将“构造过程”和他的“表示”进行分离,使得同样的构建过程可以表示不同的对象。

这个时候,需要使用 Builder 模式。用户只需指定建造者的类型就可以得到对应的产品。而具体如何构造用户并不关心。

而不同的对象的构造又是不同的,因此需要不同的建造者一一对应。

类图设计如下:

实例代码

Builer 相关:Builder, BuilderA, BuilderB

/** 抽象创建者 */
public abstract class Builder {

  abstract Product getProduct();

  abstract void builderName();

  abstract void builderBody();
}

/** 具体创建者,实际场景中,会有多个实现,即一个产品实现对应一个构建者 */
public class BuilderA extends Builder {

  Product product = new ProductA();

  @Override
  Product getProduct() {
    return product;
  }

  /** 具体构建者需要知道如何构建对象 */
  @Override
  void builderName() {
    product.name = "Name A";
  }

  @Override
  void builderBody() {
    product.body = "Body A";
  }
}

/** 具体创建者,实际场景中,会有多个实现,即一个产品实现对应一个构建者 */
public class BuilderB extends Builder {

  Product product = new ProductB();

  @Override
  Product getProduct() {
    return product;
  }

  /** 具体构建者需要知道如何构建对象 */
  @Override
  void builderName() {
    product.name = "Name B";
  }

  @Override
  void builderBody() {
    product.body = "Body B";
  }
}

Product 相关:Product,ProductA,ProductB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/** 产品,可以被抽象 */
public abstract class Product {

String name;
String body;
}
public class ProductA extends Product{
String nameA = "New A";

@Override
public String toString() {
return "ProductB{" +
"nameA='" + nameA + '\'' +
", name='" + name + '\'' +
", body='" + body + '\'' +
'}';
}
}
public class ProductB extends Product{

String nameB = "New B";

@Override
public String toString() {
return "ProductB{" +
"nameB='" + nameB + '\'' +
", name='" + name + '\'' +
", body='" + body + '\'' +
'}';
}
}

Director 相关:Director

1
2
3
4
5
6
7
8
9
/** 指挥者 */
public class Director {

/** 此方法可以固定构建对象的过程,只需要传递具体构建者即可 */
void createProduct(Builder builder) {
builder.builderName();
builder.builderBody();
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/** 测试客户端 */
public class BuilderClient {

public static void main(String[] args) {
Builder a = new BuilderA();
Builder b = new BuilderB();

Director director = new Director();
director.createProduct(a);
director.createProduct(b);

System.out.println(a.getProduct());
System.out.println(b.getProduct());
}
}

结果

1
2
ProductB{nameA='New A', name='Name A', body='Body A'}
ProductB{nameB='New B', name='Name B', body='Body B'}

从上面的代码中可以看出,通过构造不同的 Builder,可以得到对应的产品。大家可能会问,为什么不直接创建产品?实际上,生产环境中的构造过程远比 demo 复杂,将构造对象的复杂过程全部放入指挥者 Director 中,能够有效避免创建过程的错误。

通过使用 Builder,能够重复利用创建者,确保每次构造产品都是正确的。

即:

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

这里的“同样的构建过程” 就是 Director 中的 createProduct 方法。

“不同的表示”,则是每个 Builder 实现对应一个具体产品的具体构建内容。具体内容可以根据业务需求进行创建。

Spring 框架中,Builder 模式无处不在。总之,Builder 就是为了构建不同的对象的同时,提供了稳定的构建过程,所有对象的构建过程都是被 Driector 指挥的。而对象的具体构建内容则是子类 Builder 来根据需求实现。有效的将对象的内容和构建过程分离,同时也保证了构建过程的稳定,不易出错。


Builder-建造者模式
http://thinkinjava.cn/2018/06/14/2018/2018-06-14-Builder-建造者模式/
作者
莫那·鲁道
发布于
2018年6月14日
许可协议