Builder 模式:两种实现方式对比
Builder 模式:两种实现方式对比
一、简化 Builder(单一 Builder 类)
代码示例
public class ThreadFactoryBuilder {
/**
* 基础线程工厂,默认使用 Executors.defaultThreadFactory()
*/
private ThreadFactory backingThreadFactory;
/**
* 线程名前缀,如 "onethread-",线程名形如:onethread-1
*/
private String namePrefix;
/**
* 是否为守护线程,默认 false
*/
private Boolean daemon;
/**
* 线程优先级(1~10)
*/
private Integer priority;
/**
* 未捕获异常处理器
*/
private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
/**
* 创建 ThreadFactoryBuilder 实例
*/
public static ThreadFactoryBuilder builder() {
return new ThreadFactoryBuilder();
}
public ThreadFactoryBuilder threadFactory(ThreadFactory backingThreadFactory) {
this.backingThreadFactory = backingThreadFactory;
return this;
}
public ThreadFactoryBuilder namePrefix(String namePrefix) {
this.namePrefix = namePrefix;
return this;
}
public ThreadFactoryBuilder daemon(boolean daemon) {
this.daemon = daemon;
return this;
}
public ThreadFactoryBuilder priority(int priority) {
if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
throw new IllegalArgumentException("The thread priority must be between 1 and 10.");
}
this.priority = priority;
return this;
}
public ThreadFactoryBuilder uncaughtExceptionHandler(Thread.UncaughtExceptionHandler handler) {
this.uncaughtExceptionHandler = handler;
return this;
}
/**
* 构建线程工厂实例(返回另一个类型)
*/
public ThreadFactory build() {
final ThreadFactory factory = (this.backingThreadFactory != null)
? this.backingThreadFactory
: Executors.defaultThreadFactory();
Assert.notEmpty(namePrefix, "The thread name prefix cannot be empty or an empty string.");
final AtomicLong count = (StrUtil.isNotBlank(namePrefix)) ? new AtomicLong(0) : null;
return runnable -> {
Thread thread = factory.newThread(runnable);
if (count != null) {
thread.setName(namePrefix + count.getAndIncrement());
}
if (daemon != null) {
thread.setDaemon(daemon);
}
if (priority != null) {
thread.setPriority(priority);
}
if (uncaughtExceptionHandler != null) {
thread.setUncaughtExceptionHandler(uncaughtExceptionHandler);
}
return thread;
};
}
}
结构特征
┌─────────────────────────────────┐
│ ThreadFactoryBuilder │ ← Builder 类(可变)
│ ───────────────────────── │
│ - namePrefix: String │
│ - daemon: Boolean │
│ - priority: Integer │
│ ───────────────────────── │
│ + builder(): Builder │ ← 返回自己
│ + namePrefix(String): Builder │ ← 链式调用
│ + daemon(boolean): Builder │
│ + build(): ThreadFactory │ ← 返回另一个类型
└─────────────────────────────────┘
↓ build()
┌─────────────────────────────────┐
│ ThreadFactory │ ← 目标对象
│ (interface/functional object) │
└─────────────────────────────────┘
核心特点:
- Builder 是独立类,既是配置器也是构建器
- build() 返回另一个类型的对象
- 目标对象通常不需要保持不可变
- 代码简单,只有一个类
二、经典 Builder(嵌套 Builder 类)
代码示例
/**
* 线程池配置 - 经典 Builder 模式(不可变对象)
*/
public class ThreadPoolConfig {
// ===== 目标类的字段(final = 不可变) =====
private final int corePoolSize;
private final int maxPoolSize;
private final int queueCapacity;
private final String threadNamePrefix;
private final long keepAliveTime;
private final TimeUnit timeUnit;
// ===== 私有构造器(只能通过 Builder 创建) =====
private ThreadPoolConfig(Builder builder) {
this.corePoolSize = builder.corePoolSize;
this.maxPoolSize = builder.maxPoolSize;
this.queueCapacity = builder.queueCapacity;
this.threadNamePrefix = builder.threadNamePrefix;
this.keepAliveTime = builder.keepAliveTime;
this.timeUnit = builder.timeUnit;
}
// ===== 静态工厂方法(返回 Builder 实例) =====
public static Builder builder() {
return new Builder();
}
// ===== Getter 方法(没有 Setter,保证不可变) =====
public int getCorePoolSize() { return corePoolSize; }
public int getMaxPoolSize() { return maxPoolSize; }
public int getQueueCapacity() { return queueCapacity; }
public String getThreadNamePrefix() { return threadNamePrefix; }
public long getKeepAliveTime() { return keepAliveTime; }
public TimeUnit getTimeUnit() { return timeUnit; }
// ===== 静态内部 Builder 类 =====
public static class Builder {
// Builder 拥有与目标类相同的字段(可变)
private int corePoolSize = 1; // 默认值
private int maxPoolSize = 10; // 默认值
private int queueCapacity = 100; // 默认值
private String threadNamePrefix = "pool-"; // 默认值
private long keepAliveTime = 60L;
private TimeUnit timeUnit = TimeUnit.SECONDS;
// 私有构造器(强制使用外部类的 builder() 方法)
private Builder() {
}
// ===== 链式 setter 方法(返回 Builder) =====
public Builder corePoolSize(int corePoolSize) {
this.corePoolSize = corePoolSize;
return this;
}
public Builder maxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
return this;
}
public Builder queueCapacity(int queueCapacity) {
this.queueCapacity = queueCapacity;
return this;
}
public Builder threadNamePrefix(String threadNamePrefix) {
this.threadNamePrefix = threadNamePrefix;
return this;
}
public Builder keepAliveTime(long keepAliveTime, TimeUnit timeUnit) {
this.keepAliveTime = keepAliveTime;
this.timeUnit = timeUnit;
return this;
}
// ===== build() 方法(返回目标类实例) =====
public ThreadPoolConfig build() {
// 统一验证所有参数
validate();
// 创建并返回目标类的不可变实例
return new ThreadPoolConfig(this);
}
// ===== 参数验证 =====
private void validate() {
if (corePoolSize <= 0) {
throw new IllegalArgumentException("corePoolSize 必须大于 0");
}
if (maxPoolSize < corePoolSize) {
throw new IllegalArgumentException("maxPoolSize 不能小于 corePoolSize");
}
if (queueCapacity <= 0) {
throw new IllegalArgumentException("queueCapacity 必须大于 0");
}
if (threadNamePrefix == null || threadNamePrefix.isEmpty()) {
throw new IllegalArgumentException("threadNamePrefix 不能为空");
}
if (keepAliveTime < 0) {
throw new IllegalArgumentException("keepAliveTime 不能为负数");
}
}
}
// ===== 便捷方法(如创建线程池) =====
public ThreadPoolExecutor createExecutor() {
return new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime,
timeUnit,
new LinkedBlockingQueue<>(queueCapacity),
ThreadFactoryBuilder.builder()
.namePrefix(threadNamePrefix)
.build()
);
}
@Override
public String toString() {
return "ThreadPoolConfig{" +
"corePoolSize=" + corePoolSize +
", maxPoolSize=" + maxPoolSize +
", queueCapacity=" + queueCapacity +
", threadNamePrefix='" + threadNamePrefix + '\'' +
", keepAliveTime=" + keepAliveTime +
", timeUnit=" + timeUnit +
'}';
}
}
结构特征
┌─────────────────────────────────────┐
│ ThreadPoolConfig │ ← 目标类(不可变)
│ ──────────────────────────── │
│ - final corePoolSize: int │
│ - final maxPoolSize: int │
│ - final queueCapacity: int │
│ ──────────────────────────── │
│ - ThreadPoolConfig(Builder) │ ← 私有构造器
│ + builder(): Builder │ ← 返回内部 Builder
│ + getCorePoolSize(): int │
└─────────────────────────────────────┘
│
│ 包含
↓
┌─────────────────────────────────────┐
│ ThreadPoolConfig.Builder │ ← 内部 Builder(可变)
│ ──────────────────────────── │
│ - corePoolSize: int │ ← 与目标类相同的字段
│ - maxPoolSize: int │
│ - queueCapacity: int │
│ ──────────────────────────── │
│ + corePoolSize(int): Builder │ ← 链式调用
│ + maxPoolSize(int): Builder │
│ + build(): ThreadPoolConfig │ ← 返回外部类实例
└─────────────────────────────────────┘
核心特点:
- Builder 是目标类的静态内部类
- 目标类所有字段
final(不可变) build()返回目标类实例- 清晰分离"构建过程"和"最终对象"
三、两种模式对比
对比表
| 维度 | 简化 Builder(单一类) | 经典 Builder(嵌套类) |
|---|---|---|
| 类数量 | 1 个类 | 2 个类(外部类 + 内部 Builder) |
| Builder 返回值 | build() 返回另一个类型 |
build() 返回外部类实例 |
| 目标对象 | 可以是可变的 | 严格不可变(所有字段 final) |
| 字段访问 | Builder 和目标对象字段分开 | Builder 复制外部类字段 |
| 验证时机 | 可以在 setter 和 build() 都验证 | 通常只在 build() 统一验证 |
| 默认值 | 在 Builder 字段初始化 | 在 Builder 字段初始化 |
| 复杂度 | 简单 | 较复杂 |
| 类型安全 | 较低(Builder 可变) | 高(目标对象不可变) |
| 线程安全 | 需要额外处理 | 天然线程安全(不可变) |
使用方式对比
// ===== 简化 Builder =====
ThreadFactory factory = ThreadFactoryBuilder.builder()
.namePrefix("async-pool-")
.daemon(true)
.priority(7)
.build(); // 返回 ThreadFactory(另一个类型)
ExecutorService executor = Executors.newFixedThreadPool(10, factory);
// ===== 经典 Builder =====
ThreadPoolConfig config = ThreadPoolConfig.builder()
.corePoolSize(5)
.maxPoolSize(20)
.queueCapacity(200)
.threadNamePrefix("order-service-")
.keepAliveTime(120, TimeUnit.SECONDS)
.build(); // 返回 ThreadPoolConfig(不可变对象)
ThreadPoolExecutor executor = config.createExecutor();
// config 不可变,线程安全
四、使用场景决策
决策树
flowchart TD
A[需要构建复杂对象] --> B{目标对象需要
不可变性?} B -->|是| C[经典 Builder
嵌套类模式] B -->|否| D{Builder 是
目标对象本身?} D -->|是| C D -->|否| E[简化 Builder
单一类模式] C --> F[适用场景
• 配置对象
• 领域实体
• 需要线程安全] E --> G[适用场景
• 工厂/工具类
• 函数对象
• 临时对象]
不可变性?} B -->|是| C[经典 Builder
嵌套类模式] B -->|否| D{Builder 是
目标对象本身?} D -->|是| C D -->|否| E[简化 Builder
单一类模式] C --> F[适用场景
• 配置对象
• 领域实体
• 需要线程安全] E --> G[适用场景
• 工厂/工具类
• 函数对象
• 临时对象]
场景 1:工厂/工具类 → 简化 Builder
特征:
- Builder 是工具,用来创建另一个类型的对象
- 不需要保持不可变性
- 重点是"构建过程",而非"最终对象"
实际例子:
// 1. ThreadFactoryBuilder → ThreadFactory
ThreadFactoryBuilder.builder()
.namePrefix("async-")
.build() // 返回 ThreadFactory
// 2. StringBuilder → String
new StringBuilder()
.append("Hello")
.toString() // 返回 String
// 3. Stream.Builder → Stream
Stream.builder()
.add("A")
.build() // 返回 Stream
// 4. UriBuilder → URI
UriBuilder.fromUri("https://api.example.com")
.path("/users")
.queryParam("limit", 10)
.build(); // 返回 URI
// 5. RestClient.Builder → RestClient
RestClient.builder()
.baseUrl("https://api.example.com")
.build(); // 返回 RestClient
适用条件:
- 目标对象是另一个类型(工厂、接口、匿名函数)
- Builder 用完即弃,不需要长期存在
- 不需要严格的不可变性
场景 2:配置/实体对象 → 经典 Builder
特征:
- 目标对象需要不可变(线程安全)
- 参数需要验证(避免非法状态)
- 对象会在多个地方传递和使用
实际例子:
// 1. 线程池配置
ThreadPoolConfig config = ThreadPoolConfig.builder()
.corePoolSize(5)
.maxPoolSize(20)
.threadNamePrefix("order-")
.build();
// config 不可变,线程安全
// 2. HTTP 客户端配置
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new LoggingInterceptor())
.build();
// client 不可变,可以安全共享
// 3. 用户对象(领域模型)
User user = User.builder()
.id("123")
.name("Alice")
.email("alice@example.com")
.build();
// user 不可变,防止业务逻辑意外修改
// 4. Guava 不可变集合
ImmutableSet<String> set = ImmutableSet.builder()
.add("A")
.add("B")
.build();
// set 不可变,强制不可修改
// 5. RocketMQ 消息
Message msg = Message.builder()
.topic("order-created")
.body(orderJson)
.tag("payment")
.key(orderId)
.build();
// msg 不可变,保证消息一致性
适用条件:
- 需要不可变性(线程安全、防止意外修改)
- 需要严格验证(build 时检查所有参数)
- 对象会长期存在或在多线程间传递
五、优缺点总结
简化 Builder(单一类)
优点:
- 简单直接,只有一个类
- 代码量少,易于理解
- 适合工厂/工具场景
缺点:
- 目标对象可变(如果需要不可变,需要额外处理)
- 类型安全性较低
- 不适合复杂领域对象
经典 Builder(嵌套类)
优点:
- 目标对象严格不可变(线程安全)
- 类型安全,编译时保证
- 统一验证,避免非法状态
- 清晰分离"构建过程"和"最终对象"
缺点:
- 代码量大(需要维护两套字段)
- 相对复杂
- 对于简单场景可能过度设计
六、实战建议
1. 项目中如何选择?
// 使用简化 Builder:ThreadFactoryBuilder
// 原因:它是工具,用来创建 ThreadFactory
public class ThreadFactoryBuilder {
public ThreadFactory build() { /* ... */ }
}
// 使用经典 Builder:DynamicThreadPoolConfig
// 原因:配置对象需要不可变,会被多个地方引用
public class DynamicThreadPoolConfig {
private final String poolName;
private final int coreSize;
// ...
public static class Builder {
public DynamicThreadPoolConfig build() { /* ... */ }
}
}
2. 混合使用
// 配置对象用经典 Builder(不可变)
DynamicThreadPoolConfig config = DynamicThreadPoolConfig.builder()
.corePoolSize(10)
.maxPoolSize(20)
.build();
// 线程工厂用简化 Builder(工具)
ThreadFactory factory = ThreadFactoryBuilder.builder()
.namePrefix(config.getPoolName() + "-")
.build();
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
config.getCorePoolSize(),
config.getMaxPoolSize(),
// ...
);
3. 使用 Lombok 简化经典 Builder
// 使用 @Builder 自动生成经典 Builder
@Builder
public class DynamicThreadPoolConfig {
private final String poolName;
private final int corePoolSize;
private final int maxPoolSize;
private final int queueCapacity;
// 手动添加验证
public static class Builder {
public DynamicThreadPoolConfig build() {
if (corePoolSize <= 0) {
throw new IllegalArgumentException("corePoolSize 必须大于 0");
}
return new DynamicThreadPoolConfig(this);
}
}
}
// 使用方式
DynamicThreadPoolConfig config = DynamicThreadPoolConfig.builder()
.poolName("order-service")
.corePoolSize(10)
.maxPoolSize(20)
.build();
七、快速选择指南
| 场景 | 推荐模式 | 典型例子 |
|---|---|---|
| 工厂/工具类 | 简化 Builder | ThreadFactoryBuilder → ThreadFactory |
| 配置对象 | 经典 Builder | ThreadPoolConfig |
| 领域实体 | 经典 Builder | User、Order |
| 集合构建 | 简化 Builder | ImmutableList.builder() |
| 流式 API | 简化 Builder | Stream.Builder |
| 不可变需求 | 经典 Builder | OkHttpClient |
核心原则
- 需要不可变性 → 经典 Builder(嵌套类)
- 创建其他类型 → 简化 Builder(单一类)
- 简单工具 → 简化 Builder(单一类)
- 复杂配置 → 经典 Builder(嵌套类)