跳到主要内容

建造者模式

问题

什么是建造者模式?什么时候使用?与工厂模式有什么区别?

答案

核心思想

将复杂对象的构造过程分步骤进行,允许用户只通过需要的步骤来构造对象。特别适合参数多、组合方式多的场景。

使用场景

  • 构造器参数 > 4 个
  • 有多个可选参数
  • 参数之间存在约束关系
  • 希望对象创建后不可修改(immutable)

经典实现

Builder 模式
public class HttpRequest {
private final String url; // 必填
private final String method; // 必填
private final Map<String, String> headers; // 可选
private final String body; // 可选
private final int timeout; // 可选

private HttpRequest(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = Collections.unmodifiableMap(builder.headers);
this.body = builder.body;
this.timeout = builder.timeout;
}

public static class Builder {
// 必填参数
private final String url;
private final String method;
// 可选参数 - 设默认值
private Map<String, String> headers = new HashMap<>();
private String body;
private int timeout = 5000;

public Builder(String url, String method) {
this.url = url;
this.method = method;
}

public Builder header(String key, String value) {
this.headers.put(key, value);
return this; // 返回 this 支持链式调用
}

public Builder body(String body) {
this.body = body;
return this;
}

public Builder timeout(int timeout) {
this.timeout = timeout;
return this;
}

public HttpRequest build() {
// 校验参数
if (url == null || url.isEmpty()) {
throw new IllegalStateException("URL 不能为空");
}
return new HttpRequest(this);
}
}
}

// 使用:链式调用,清晰易读
HttpRequest request = new HttpRequest.Builder("https://api.example.com", "POST")
.header("Content-Type", "application/json")
.body("{\"name\": \"test\"}")
.timeout(3000)
.build();

Lombok @Builder

实际项目中通常用 Lombok 自动生成 Builder 代码。

Lombok @Builder
@Builder
@Getter
public class UserDTO {
private final String name;
private final String email;
@Builder.Default
private final String role = "USER";
}

// 使用
UserDTO user = UserDTO.builder()
.name("张三")
.email("zhangsan@example.com")
.build();

Java 中的 Builder 应用

说明
StringBuilder逐步构建字符串
Stream.Builder构建 Stream
Locale.Builder构建 Locale
OkHttp Request.Builder构建 HTTP 请求
Spring UriComponentsBuilder构建 URI
MockMvcRequestBuilders构建测试请求

常见面试问题

Q1: 建造者模式和工厂模式的区别?

答案

维度工厂模式建造者模式
关注点创建哪种类型的对象如何构造一个复杂对象
构建过程一步到位分步骤逐步构建
使用场景多种产品类型一种产品,多种配置

Q2: 为什么 Builder 比多参数构造器好?

答案

// 多参数构造器:参数含义不直观,容易传错位置
new User("张三", "zhangsan@mail.com", 25, "USER", true, null);

// Builder:每个参数都有名字,可读性强
User.builder()
.name("张三")
.email("zhangsan@mail.com")
.age(25)
.build();

优势:可读性好、可选参数灵活、便于校验、对象不可变。

相关链接