【设计模式系列】建造者模式 前言 建造者模式结构 建造者模式

这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

前言

建造者设计模式和工厂模式,抽象工厂模式一样也是创建型设计模式之一。

如果在需要创建一个对象时,该对象包含大量的参数,使用工厂模式或抽象工厂模式会存在一些问题。为了解决这些问题,可以使用建造者模式。

工厂模式和抽象工厂模式在这种情况下主要存在下列问题:

  • 有太多参数需要从客户端传递给工厂类,这很容易出错,尤其是当有很多数据类型一样的参数时,很难正确维护参数的顺序;
  • 如果有参数是可选的,则需要在参数列表中传递NULL值;
  • 如果对象很重,创建起来很复杂,那么这些复杂性都会侵入到工厂类中;
  • 这种问题虽然可以通过提供一个包含所有必须参数的构造方法,然后其他可选参数使用setter方法来设置,但是这样容易造成对象状态的不一致。

为了解决这一系列问题,在建造者模式中,通过提供一种逐步构建对象的方法,并将最终对象返回,可以解决大量参数和对象状态不一致的问题。

建造者模式结构

如果实现建造者设计模式,主要分以下步骤:

  • 首先创建一个静态内部类,将所有需要构建对象的属性赋值到内部类中;按照约定的命名规范,一般命名为XXXBuilder,比如需要创建一个Computer对象,则静态内部类为ComputerBuilder;
  • 这个Builder类需要提供一个包含所有参数的构造方法;
  • 然后Builder类还需要提供设置可选参数的方法,该设置方法需要将Builder对象返回;
  • 最后需要在Builder类中提供build()方法,该方法将返回客户端最终需要的对象,也就是Computer对象。

代码结构如下:

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
88
89
90
91
92
93
94
95
96
97
98
java复制代码package com.heiz.design.builder;

/**
* @author 小黑说Java
* @ClassName Computer
* @Description
* @date 2021/11/20
**/

public class Computer {

//必选参数
/**
* 硬盘
*/
private String HDD;
/**
* 内存
*/
private String RAM;

// 可选参数
/**
* 显卡
*/
private boolean isGraphicsCardEnabled;
/**
* 蓝牙
*/
private boolean isBluetoothEnabled;


public String getHDD() {
return HDD;
}

public String getRAM() {
return RAM;
}

public boolean isGraphicsCardEnabled() {
return isGraphicsCardEnabled;
}

public boolean isBluetoothEnabled() {
return isBluetoothEnabled;
}

private Computer(ComputerBuilder builder) {
this.HDD = builder.HDD;
this.RAM = builder.RAM;
this.isGraphicsCardEnabled = builder.isGraphicsCardEnabled;
this.isBluetoothEnabled = builder.isBluetoothEnabled;
}

//Builder Class
public static class ComputerBuilder {

//必选参数
/**
* 硬盘
*/
private String HDD;
/**
* 内存
*/
private String RAM;

// 可选参数
/**
* 显卡
*/
private boolean isGraphicsCardEnabled;
/**
* 蓝牙
*/
private boolean isBluetoothEnabled;

public ComputerBuilder(String hdd, String ram) {
this.HDD = hdd;
this.RAM = ram;
}

public ComputerBuilder setGraphicsCardEnabled(boolean isGraphicsCardEnabled) {
this.isGraphicsCardEnabled = isGraphicsCardEnabled;
return this;
}

public ComputerBuilder setBluetoothEnabled(boolean isBluetoothEnabled) {
this.isBluetoothEnabled = isBluetoothEnabled;
return this;
}

public Computer build() {
return new Computer(this);
}
}
}

需要注意,Computer类只有getter方法,没有公共构造函数。因此,获得Computer对象的唯一方法是通过ComputerBuilder类。

然后我们使用一个简单的测试,来测一下我们的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
java复制代码package com.heiz.design.builder;

/**
* @author 小黑说Java
* @ClassName BuilderTest
* @Description
* @date 2021/11/20
**/
public class BuilderTest {
public static void main(String[] args) {
Computer computer = new Computer.ComputerBuilder("500GB", "2 GB")
.setBluetoothEnabled(false)
.setGraphicsCardEnabled(true)
.build();
}
}

建造者模式的优点

使用建造者模式将创建对象的可变属性和不可变属性进行分离,对于客户端只能使用建造者创建对象,不用关心创建细节,所以建造者模式更易于扩展,便于控制细节风险。

JDK中的建造者模式

在JDK中最典型的建造者模式就是我们常用的StringBuilder和StringBuffer:

  • java.lang.StringBuilder#append() 线程不安全
  • java.lang.StringBuffer#append() 线程安全

以上就是本期建造者模式的全部内容,如果对你有所帮助,点个赞是对我最大的鼓励。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%