You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何在Builder设计模式中需要使用Builder类?

Builder模式里内部Builder类的作用,为啥不用链式Setter?

一、内部Builder类到底是干啥的?

内部Builder类核心就是帮你安全、清晰地创建一个完整的对象,具体说有这几个关键目的:

  • 锁住对象的不可变性:目标类(比如示例里的Employee)写完构造器就没别的修改入口了,一旦通过build()创建出来,字段就不能再改。这种不可变对象在多线程场景下天生安全,也不会被意外修改导致bug。
  • 统一做参数校验:你可以在Builder的build()方法里加校验逻辑,比如判断id不能是负数、name不能为空,确保创建出来的对象一定是合法有效的,不会出现半初始化的状态。
  • 解决多字段构造的混乱:如果类有10个字段,写一堆参数不同的重叠构造器会让人晕头转向,用Builder的链式调用id(1).name("Abc"),谁看都知道每个字段对应啥值,可读性拉满。

二、为啥不直接用链式Setter?

你给的第二种链式Setter写法看起来简洁,但藏着不少坑:

  • 对象永远可变:创建完new Employee().id(1).name("Abc")之后,别人还能调用emp.id(2)改字段,要是在多线程里,一个线程读一个线程改,很容易出问题;而且如果是业务上不允许修改的对象,这种写法根本没法保证。
  • 没法确保对象完整:万一你漏写了id(1),那Employee的id就是默认值0,这个无效对象就直接流入业务逻辑了。但Builder模式可以在build()里强制检查必填字段,没填就抛异常,从根源避免这种情况。
  • 语义完全不一样:链式Setter是在修改一个已存在的对象,而Builder的链式调用是在组装一个即将创建的对象,build()方法明确告诉你“好了,现在这个对象完整了,可以用了”,语义上更贴合对象初始化的场景。

两种写法对比

Builder模式实现

public class Employee {
  private int id;
  private String name;

  public Employee (Builder builder) {
    this.id = builder.id;
    this.name = builder.name;
  }

  public static class Builder {
    private int id;
    private String name;

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

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

    public Employee build() {
      // 这里可以加校验:比如id <=0 抛异常,name为空抛异常
      return new Employee(this);
    }
  }
}

// 使用方式
Employee emp = new Employee.Builder().id(1).name("Abc").build();

链式Setter实现

public class Employee {
  private int id;
  private String name;

  public Employee id(int id) {
    this.id = id;
    return this;
  }

  public Employee name(String name) {
    this.name = name;
    return this;
  }
}

// 使用方式
Employee emp = new Employee().id(1).name("Abc");

内容的提问来源于stack exchange,提问作者Shameem94

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 02:59:53