设计模式-建造者模式

建造者模式(Builder Pattern): 将一个复杂对象的构建与它的表示分离, 使得同样的构建过程可以创建不同的表示.

设计模式-概述

当有一个复杂对象需要构造, 对象内部各个组件均有很多平级配置, 构建者并不关心组件的内部结构, 此时使用建造者模式能很好的解决这种问题. 例如组装一个高达, 主要组成有:头部,身体,四肢. 这三个具体组成并不关心, 是个完整的头, 身体, 四肢就行了, 并且头部可能有各种颜色的, 身体,四肢也有各种不同的, 将会有不同的组合, 使用已有的组合将会是封闭的, 新增组合会是开放的, 符合”开闭原则”.

结构

组成部分为:

  1. Builder : 抽象建造者
  2. ConcreteBuilder : 具体建造者
  3. Director : 指挥者
  4. Product : 产品

builder-1.png

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
@startuml builder-1
!include common.cuml

Class(Product,"产品") {
}

Interface(Builder,"抽象建造者") {
+ setPart1() : void
+ setPart2() : void
+ setPart3() : void
+ getResult() : void
}

Class(ConcreteBuilder,"具体建造者") {
+ setPart1() : void
+ setPart2() : void
+ setPart3() : void
+ getResult() : void
}

Class(Director,"指挥者") {
- builder : Builder
+ setBuilder() : void
+ buildProduct() : Product
}

Director o-right- Builder
Builder <|... ConcreteBuilder
ConcreteBuilder .up.> Product
@enduml

使用时序

builder-2.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@startuml builder-2

actor 用户 as U
participant Director as D
participant ConcreteBuilder as C

U --> C : <<create>> 我要用这个创建产品
U -> D : setBuilder(builder)
U -> D : buildProduct() : Product
activate D
D -> C : setPart1()
D -> C : setPart2()
D -> C : setPart3()
D -> C : getResult()
D -> U : 收到ConcreteBuilder创建的Product
deactivate D

@enduml

代码实现

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
* CreateUser: canyuda
* CreateTime: 2019/9/29 21:26
* Description:
*/
public class Main {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director();
director.setBuilder(builder);
Product product = director.buildProduct();
System.out.println(product.desc());
}
}

class Product {

private String part1;
private String part2;
private String part3;

Product(String part1, String part2, String part3) {
this.part1 = part1;
this.part2 = part2;
this.part3 = part3;
}

public String desc() {
return "产品这个样子:" + part1 + "_" + part2 + "_" + part3;
}
}

interface Builder {
void setPart1();

void setPart2();

void setPart3();

Product getResult();
}

class ConcreteBuilder implements Builder {

private String part1;
private String part2;
private String part3;

@Override
public void setPart1() {
System.out.println("安装组件1");
this.part1 = "组件1";
}

@Override
public void setPart2() {
System.out.println("安装组件2");
this.part2 = "组件2";
}

@Override
public void setPart3() {
System.out.println("安装组件3");
this.part3 = "组件3";
}

@Override
public Product getResult() {
return new Product(part1, part2, part3);
}
}

class Director {
private Builder builder;

public void setBuilder(Builder builder) {
this.builder = builder;
}

Product buildProduct() {
builder.setPart1();
builder.setPart2();
builder.setPart3();
return builder.getResult();
}

}

使用场景

  • 生成的产品有复杂的结构, 各个成员间性质差别明确.
  • 属性之间可能有联系, 可能有特定的生成顺序.
  • 隔离复杂对象的创建和使用, 并使得相同的创建过程可以创建不同的产品, 仅需要实现建造者接口即可.

具体应用

  1. protobuf 对象的创建使用了建造者模式(变种)

    1
    2
    3
    4
    SimpleRequest.Builder builder = SimpleRequest.newBuilder();
    builder.setId(12341);
    builder.setName("你好");
    SimpleRequest request = builder.build();
  2. Android 中AlertDialog使用

    1
    2
    3
    4
    5
    new AlertDialog.Builder(this)
    .setCancelable(true)
    .setIcon(R.mipmap.app_logo)
    .setMessage("温馨提醒")
    .show();