Post

静态工厂方法和构建器模式

静态工厂方法和构建器模式
注意区分“构建器模式”和普通“构造器”(new方法)!

静态工厂方法和构建器模式(Builder Pattern)是两种不同的设计模式,虽然它们都用于对象创建,但解决的问题和适用场景有显著差异。以下是它们的核心区别:


1. 核心目的不同

模式核心目的
静态工厂方法简化对象创建,隐藏构造细节,提供更灵活的对象实例化方式(例如返回子类、缓存对象等)。
构建器模式解决复杂对象的构造问题,尤其是当对象有大量可选参数或需要分步构造时,避免构造函数参数爆炸。

2. 典型代码结构对比

静态工厂方法

1
2
3
4
5
6
7
8
9
10
11
12
public class MyClass {
    // 静态工厂方法
    // 直接根据传入的参数构造对象
    public static MyClass create(String param) {
        return new MyClass(param);
    }

    private MyClass(String param) { /* ... */ }
}

// 使用
MyClass obj = MyClass.create("value");

构建器模式

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
public class MyClass {
    private final String param1;
    private final int param2;

    // 构建器
    public static class Builder {
        private String param1;
        private int param2 = 0; // 默认值

		// 有不同方法设置对象属性
        public Builder param1(String val) {
            this.param1 = val;
            return this;
        }

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

		// 最后生成对象
        public MyClass build() {
            return new MyClass(this);
        }
    }

    private MyClass(Builder builder) {
        this.param1 = builder.param1;
        this.param2 = builder.param2;
    }
}

// 使用
MyClass obj = new MyClass.Builder()
    .param1("value")
    .param2(42)
    .build();

3. 关键区别

特性静态工厂方法构建器模式
参数处理通常需要一次性传递所有参数(或通过重载)支持分步设置参数,可选参数可忽略或设默认值
可读性方法名可自解释(如 fromJson链式调用,参数意义更清晰(如 .name("Alice")
适用场景简单对象创建、对象复用、多态返回复杂对象构造(如含多个可选参数或配置项)
代码复杂度简单需要额外编写 Builder 类,代码量较多
线程安全性通常线程安全(无中间状态)Builder 的中间状态可能非线程安全
典型应用Integer.valueOf()Collections.emptyList()StringBuilder、Flink/Spark 的配置类

4. 适用场景示例

静态工厂方法

  • 场景1:隐藏构造函数细节(如返回缓存对象)

    1
    2
    3
    4
    5
    6
    7
    8
    
      public class Logger {
          private static final Logger INSTANCE = new Logger();
            
          // 静态工厂方法
          public static Logger getInstance() {
              return INSTANCE;
          }
      }
    
  • 场景2:根据输入返回不同子类

    1
    2
    3
    4
    5
    6
    
      public abstract class Shape {
          public static Shape create(String type) {
              if ("circle".equals(type)) return new Circle();
              else return new Rectangle();
          }
      }
    

构建器模式

  • 场景1:构造含多个可选参数的对象

    1
    2
    3
    4
    5
    
      HttpClient client = new HttpClient.Builder()
          .url("https://example.com")
          .timeout(5000)
          .retry(3)
          .build();
    
  • 场景2:分步配置复杂对象(如 Flink 的 StreamExecutionEnvironment

    1
    2
    3
    4
    
      FileSink<String> sink = FileSink.forRowFormat(...)
          .withBucketAssigner(...)
          .withRollingPolicy(...)
          .build();
    

5. 为什么不能混用?

  • 静态工厂方法 可以返回任意对象(包括不同子类或缓存实例),但不解决参数过多的问题
  • 构建器模式 专门解决参数过多和可选参数问题,但需要为每个类单独实现 Builder

总结

模式用一句话概括
静态工厂方法“通过一个静态方法,直接给你一个对象。”
构建器模式“通过链式调用一步步配置参数,最后生成一个对象。”

根据需求选择:

  • 若对象简单且参数少 → 静态工厂方法
  • 若对象复杂、参数多或需分步配置 → 构建器模式
This post is licensed under CC BY 4.0 by the author.